TaurusDB索引设计规范
- 避免因为字段类型不同造成的隐式转换,导致索引失效。
- 业务上具有唯一特性的字段,即使是多个字段的组合,建议在所有具有唯一特性字段的最小集合上建立唯一索引。
- 尽量在定长的字段(如:INT)上建立索引;在VARCHAR字段上建立索引时,必须指定索引长度,无需对全字段建立索引,根据实际文本区分度决定索引长度即可。
索引长度与区分度是一对矛盾体,一般对字符串类型数据,长度为20的索引区分度会高达90%以上,可以使用COUNT(DISTINCT LEFT(列名,索引长度))/COUNT(*)的区分度来确定。(有区分度的放前面,没有区分度的放后面)。
- 页面搜索避免使用左模糊(如:SELECT * FROM users WHERE u_name LIKE ‘%hk’)或者全模糊,避免从索引扫描退化为全表扫描,如果需要请在应用层解决。
索引文件具有B-tree的最左前缀匹配特性,如果左边的值未确定,那么无法使用此索引。
- 利用覆盖索引来进行查询操作,避免回表,但是覆盖索引加的字段不能太多,要兼顾写性能。
能够建立索引的种类:主键索引、唯一索引、普通索引,而覆盖索引是一种查询的效果,利用explain的结果,extra列会出现:using index。
- SQL性能优化的目标:至少要达到range级别,要求是ref级别,如果可以是consts最好。
- 创建组合索引的时候,区分度最高的在左边。
- 单张表的索引数量控制在5个以内,或不超过表字段个数的20%。
- 创建索引避免有如下误解:
- 宁滥勿缺。误认为一个查询就需要建一个索引。
- 宁缺勿滥。误认为索引会消耗空间、严重拖慢更新和新增速度。
- 抵制唯一索引。误认为业务的唯一性一律需要在应用层通过“先查后插”方式能解决。
- 根据实际业务需求,减少使用无法利用索引优化的order by查询语句。Order by、group by、distinct这些语句较为耗费CPU资源。
- 涉及到复杂SQL语句时,优先参考已有索引进行设计,通过执行explain,查看执行计划,利用索引,增加更多查询限制条件。
- 使用新的SELECT、UPDATE、DELETE语句时,都需要通过explain查看执行计划中的索引使用情况,尽量避免extra列出现:Using File Sort,Using Temporary。当执行计划中扫描的行数超过1000时,需要评估是否允许上线。需每日进行慢日志统计分析,处理慢日志语句。
explain解读:
- type:ALL, index, range, ref, eq_ref, const, system, NULL(从左到右,性能从差到好)。
- possible_keys:指出MySQL能使用哪个索引在表中找到记录,查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询使用。
- key:表示MySQL实际决定使用的键(索引),如果没有选择索引,键是NULL。要想强制MySQL使用或忽视possible_keys列中的索引,在查询中使用FORCE INDEX、USE INDEX 或者IGNORE INDEX。
- ref:哪些列或常量被用于查找索引列上的值。
- rows:根据表统计信息及索引选用情况,估算的找到所需的记录所需要读取的行数。
- Extra:
- Using temporary:表示MySQL需要使用临时表来存储结果集,常见于排序和分组查询。
- Using filesort:MySQL中无法利用索引完成的排序操作称为“文件排序”。
- Using index:表示使用索引,如果只有 Using index,说明没有查询到数据表,只用索引表即完成了这个查询,这种情况为覆盖索引。如果同时出现Using where,代表使用索引来查找读取记录, 也是可以用到索引的,但是需要查询到数据表。
- Using where:表示条件查询,如果不读取表的所有数据,或不是仅仅通过索引就可以获取所有需要的数据,则会出现 Using where。如果type列是ALL或index,而没有出现该信息,则你有可能在执行错误的查询,返回所有数据。
- 在WHERE条件列上使用函数,会导致索引失效。
示例:如 WHERE left(name, 5) = 'zhang',left函数会导致name上的索引失效。
修改方案:可在业务侧修改该条件,不使用函数。当返回结果集较小时,业务侧过滤满足条件的行。
- 对于超大表,在索引使用上还需要遵循以下规范。
- 要根据查询有针对性的创建,考虑在WHERE和ORDER BY命令上涉及的列建立索引,可根据EXPLAIN来查看是否用了索引还是全表扫描。
- 值分布很稀少的字段不适合建索引,例如“性别”这种只有两三个值的字段。
- 字符字段不要做主键。
- 不用外键,由程序保证约束。
- 使用多列索引时注意顺序和查询条件保持一致,同时删除不必要的单列索引。
- 删除索引,要做充分论证,最好做数据备份。