索引使用建议:
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 = 1
union
a = 5
索引设计建议:
a,一个索引里包含的个数最好不要超过5个
b,一个表的索引数,不要太多,一般不要超过5个
c,联合索引中把过滤性高(基数大)的列放在前面
来源:https://www.cnblogs.com/xxmysql/p/5907888.html