mysql建表优化注意事项

一、建表原则

1. 定长与变长分离

所谓定长,就是字段的长度是固定大小。如int占四个字节,char(4)占四个字符,一些核心并且常用的字段,应该设置为定长。而变长如varchar,text等类型的字段长度不一,适合单放一张表,用主键与核心表关联起来。

2. 常用字段要与非常用字段分离

需要结合网站的具体业务分析,分析字段的查询场景,查询频率低的字段单拆出来

3. 适当增加冗余字段

在一对多,需要关联统计的字段上增加冗余字段。例如文章类型表对应文章表,一对多。我们需要查看一种文章类型中有多少篇文章,此时可以在文章类型表中添加文章数量字段,避免关联查询。

二、列类型选择

1. 字段类型优先级

整型 > date,time > emum char > varchar > blob,text

选用字段长度最小、优先使用定长型、数值型字段中避免使用 “ZEROFILL”。

  • time : 定长运算快,节省时间,考虑时区,写sql不方便
  • enum : 能约束值的目的,内部用整形来储存,但与char联查时,内部要经历串与值的转化
  • char : 定长,考虑字符集和校对集
  • varchar : 不定长,要考虑字符集的转换与排序时的校对集,速度慢
  • text,blob : 无法使用内存临时表(排序操作只能在磁盘上进行)

注意:date,time的选择可以直接选择使用时间戳,enum("男","女") //内部转成数字来储存,多了一个转换的过程,可以使用tinyint代替最好使用tinyint。

2. 可以选整型就不选字符串

整型是定长的,没有国家/地区之分,没有字符集差异。例如:tinyint 和 char(1) 从空间上看都是一字节,但是 order by 排序 tinyint 快。原因是后者需要考虑字符集与校对集(就是排序优先集)。

3. 够用就行不要慷慨

大的字段影响内存影响速度。以年龄为例:tinyint unsigned not null;可以储存255岁,足够了,用int浪费3个字节。以varchar(10),varchar(300)储存的内容相同,但在表中查询时,varhcar(300)要花用更多内存。

4. 尽量避免使用NULL

Null不利于索引,也不利于查询。=null或者!= null都查询不到值,只有使用is null或者is not null才可以。因此可以在创建字段时候使用 not null default "" 的形式。

5. char与varchar选择

char长度固定,处理速度要比varchar快很多,但是相对较费存储空间;所以对存储空间要求不大,但在速度上有要求的可以使用char类型,反之可以用varchar类型。

char:长度固定,比较适合存储很短数据、固定长度(比如使用uuid作为主键)、十分频繁改变的column的字段;char(M)类型的数据列里,每个值都占用M个字节,如果某个长度小于M,MySQL就会在它的右边用空格字符补足。(在检索操作中那些填补出来的空格字符将被去掉)

varchar:可变长度,占用长度为字符数+1(用来存储位置)

三、其他注意事项

1. 列类型转换规则

在MySQL中用来判断是否需要进行对据列类型转换的规则

  • 在一个数据表里,如果每一个数据列的长度都是固定的,那么每一个数据行的长度也将是固定的.
  • 只要数据表里有一个数据列的长度的可变的,那么各数据行的长度都是可变的.
  • 如果某个数据表里的数据行的长度是可变的,那么,为了节约存储空间,MySQL会把这个数据表里的固定长度类型的数据列转换为相应的可变长度类型.但长度小于4个字符的char数据列不会被转换为varchar类型
  • 导致实际应用中varchar长度限制的是一个行定义的长度。 MySQL要求一个行的定义长度不能超过65535。

2. 主键和外键

主键:尽可能使用长度短的主键,如果可以使用外键做主键则更好。在主键上无需建单独的索引,因为系统内部为主键建立了聚簇索引。

外键:外键会影响插入和更新性能,对于批量可靠数据的插入,建议先屏蔽外键检查。 对于数据量大的表,建议去掉外键,改由应用程序进行数据完整性检查。

尽可能用选用对应主表的主键作作为外键,避免选择长度很大的主表唯一键作为外键。

外键是默认加上索引的。

3. 索引

对于那些在查询中很少使用或者参考的列不应该创建索引。费空间

对于那些只有很少数据值的列也不应该增加索引。映射太少

对于那些定义为text, image和bit数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少。

当修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。

①. 被索引的字段的长度越小,该索引的效率越高

②. 被索引的字段中,值的重复越少, 该索引的效率越高

③. 查询语句中,如果使用了 “group”子句, 根据其中字段出现的先后顺序建立多字段索引

④. 查询语句中,如果使用了 “distinct”,根据其中字段出现的先后顺序建立多字段索引

⑤. “where”子句中, 出现对同一表中多个不同字段的 “and”条件时, 按照字段出现的先后顺序建立多字段索引

⑥. “where”子句中, 出现对同一表中多个不同字段的 “or”条件时, 对重复值最少的字段建立单字段索引

⑦. 进行 “内/外连接”查询时, 对 “连接字段”建立索引

⑧. 对 “主键”的 “unique” 索引毫无意义,不要使用。对于一个Primary Key的列,MySQL已经自动对其建立了Unique Index,无需重复再在上面建立索引了。

⑨. 被索引字段尽可能的使用 “NOT NULL”属性

⑩. 对写入密集型表,尽量减少索引, 尤其是 “多字段索引”和 “unique” 索引

⑪. MySQL只会使用前缀,例如key(a, b) …where b=5将使用不到索引。

⑫. 控制单个索引的长度。使用key(name(8))在数据的前面几个字符建立索引

⑬. 相近的键值比随机好。Auto_increment就比uuid好。

4. 查询优化

①. 多多利用 “explain”查询索引使用情况, 以便找出最佳的查询语句写法和索引设置方案

②. 慎用 “select *”,查询时只选出必须字段

③. 查询使用索引时,所遍历的索引条数越少,索引字段长度越小, 查询效率越高 (可使用 “explain”查询索引使用情况)

④. 避免使用 mysql函数对查询结果进行处理,将这些处理交给客户端程序负责

⑤. 使用 “limit”时候, 尽量使 “limit” 出的部分位于整个结果集的前部, 这样的查询速度更快, 系统资源开销更低

⑥. 在 “where”子句中使用多个字段的 “and”条件时, 各个字段出现的先后顺序要与多字段索引中的顺序相符

⑦. 在 “where”子句中使用 “like”时, 只有当通配符不出现在条件的最左端时才会使用索引

⑧. 在 mysql 4.1以上版本中, 避免使用子查询, 尽量使用 “内/外连接”实现此功能

⑨. 减少函数的使用,如果可能的话, 尽量用单纯的表达式来代替

⑩. 避免在 “where”子句中, 对不同字段进行 “or” 条件查询, 将其拆分成多个单一字段的查询语句效率更高

⑪. 查询时使用匹配的类型。例如select * from awhere id=5,如果这里id是字符类型,同时有index,这条查询则使用不到index,会做全表扫描,速度会很慢。正确的应该是… where id=”5” ,加上引号表明类型是字符。

weinxin
我的微信
扫一扫加我微信
琪玥

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: