mysql索引

蓝咒 提交于 2020-02-12 05:40:28

索引使用建议:

a,经常检索的列

b,经常用于表连接的列

c,经常排序/分组的列

索引不使用建议:

a,基数很低的列

b,经常用于表连接的列

c,经常排序/分组的列

 

innodb主键特点:

a,索引定义时,若不显示包含主键,会隐式加入主键值;

b,索引定义时,若显示包含主键,会加入主键值;

c,在5.6.9后,优化器已经能自动识别索引末尾的主键值(index extensions),在这之前则需要显式加上主键列才可以被识别;

d,修改主键必然重新拷贝整张表

 

主键的选择建议:

a,对业务透明无意义,免收业务变化的影响;

b,主键要很少修改和删除;(删除还好,影响不大,innodb小范围做数据页合并)

c,主键最好是自增的;

d,不要具有动态属性,例如最后修改时间戳;(如果经常变化会导致聚集索引的值发生变化,相应的导致btree索引值旋转、分裂、位移)

 

innodb聚集索引选择顺序原则:

a,显示声明的主键;

b,第一个不包含null值的唯一索引列;

c,内置的rowid(自增逻辑值,6byte且不可引用)

 innodb聚集索引不建议选用频繁更新、随机写入(离散IO)

 

唯一索引(unique key)

a,不允许具有索引值相同的行,从而禁止重复的索引或键值;

b,在唯一约束上,和主键一样(以myisam引擎为代表);

c,和主键区别:1,唯一索引允许有空值(null) 2,一个表只能有一个主键,但可以有多个唯一索引 3,innodb表中主键必须是聚集索引,但聚集索引可能不是主键(未定义主键、也没有非null的唯一索引时会选择rowid) 4,唯一索引约束可以临时禁用,但主键不行(set session  UNIQUE_CHECKS = 0;),即便禁用唯一性约束,也无法插入相同值。那么,关闭还有什么意义?大量导入数据时就不需要每行都检测唯一性是否冲突,最后一次性检测有没有重复,效率更高些。如果不想告警可以使用 on duplicate key update(先insert,如果失败就update);

 

联合索引(combined indexes,multiple-column indexes)

a,多列组成,所以也叫多列索引

b,适合where条件中的多列组合

c,有时候,还可以用于避免回表(覆盖索引)

d,以往有列引用顺序,现在已经没有这个限制了

e,mysql还不支持多列不同排序规则(order by a.b.c,desc;这个不ok)

f,联合索引建议:1,where条件中,经常同时出现的列放在联合索引中。2,联合索引包含的列数越多,会增加死锁的概率。

 

覆盖索引:

a,通过索引数据结构,即可直接返回数据,不需要回表

b,执行计划中,显示关键字using index

 

前缀索引(prefix indexes):

部分索引的原因:1,char/varchar太长全部做索引的话,效率太差,存在浪费。2,blob/text类型不能整列作为索引列,因此需要前缀索引。

部分索引的选择建议:1,统计平均值。2,遵循2/8原则(覆盖80%数据就OK)

 

外键约束(foreign key constraints)

a,确保存储在外键表中的数据一致性,完整性;

b,外键前提:本表列须与外键类型相同(外键须是外表主键);

c,外键选择原则:1,为关联字段创建外键。2,所有的键都必须唯一。3,避免使用复合键;4,外键总是关联唯一的键字段。

mysql支持全文索引,但不建议使用IO,内存,CPU都是瓶颈。

 可以使用pt-duplicate-key-checker检查冗余索引,pt-index-usage检查低利用率索引,并提供删除建议。

 

索引如何提高sql效率?

a,提高数据检索效率

b,提高聚合函数效率,sum()、avg()、count()

c,有时可以避免回表

d,减少多表关联扫描行数

e,唯一、外键索引还可以作为辅助约束

f,列定义DEFAULT NULL时,NULL值也会有索引,存放在索引树的最左端,最前端部分,因此尽量不要定义为NULL。

 

什么时候索引不可用?

a,通过索引扫描的记录数超过30%,会变成全表扫描

b,联合索引中,第一个索引列使用范围查询(这时用到部分索引)

c,联合索引中,第一个查询条件不是最左索引列

d,模糊查询条件列最左通配符%开始

e,HEAP表使用HASH索引时,使用范围检索或者ORDER BY

f,多表关联时,排序字段不属于驱动表,无法利用索引完成排序(这点很重要,详见下图案例,强制更改驱动表可能影响结果集)

g,两个独立索引,其中一个用于检索,一个用于排序(只能用到一个)

 

 

ICP(index condition pushdown)是mysql5.6的新特性,其机制会让索引的其他部分也参与过滤,减少引擎层和server层数据传输和回表请求,通常情况下可大幅度提升查询效率。

 

覆盖索引:

假设有这样的索引:key 'idx1'('id','user','passwd')

覆盖索引都被用到:

a,select id,user,passwd from t1 where id=?

b,select id,user,passwd from t1 where id=? and user=?

c,select id,user,passwd from t1 where id=? and user=? and passwd=?

覆盖索引部分被用到:

a,select id,user,passwd from t1 where passwd=? and id=?

b,select id,user from t1 where id =? order by user;

c,select id,user from t1 where id=? order by passwd;

 

explain之key_len

a,正常情况等于索引列字节长度

b,字符串类型需要同时考虑字符集因素

c,若允许null,再+1

d,变长类型(如varchar)再+2

 key_len只计算利用索引完成数据过滤的索引长度

不包括用于group by\order by的索引长度

即:如果order by也使用了索引,不会将其计算在key_len之内

例如:联合索引(c1,c2,c3),where c1 = ? and c2 = ? order by c3.这时,key_len只会显示c1+c2的长度

#eq_range_index_dive_limit  默认值是200,in值只要不超过200都是等值查询,超过200执行代价会有变化。

 

a in (1, 5) 等价于
a = 1
union
a = 5

 

索引设计建议:

a,一个索引里包含的个数最好不要超过5个

b,一个表的索引数,不要太多,一般不要超过5个

c,联合索引中把过滤性高(基数大)的列放在前面

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!