云数据库 GAUSSDB(FOR MYSQL)-索引设计规范

时间:2024-07-03 11:01:10

索引设计规范

  • 避免因为字段类型不同造成的隐式转换,导致索引失效。
  • 业务上具有唯一特性的字段,即使是多个字段的组合,建议在所有具有唯一特性字段的最小集合上建立唯一索引。
    例如:一个表含有有a,b,c,d,e,f字段,在业务上ab和ef分别是具有唯一特性的字段集合,那么最好在最小集合ab和ef上分别建立唯一索引。

    即使在应用层做了完善的校验控制,只要没有唯一索引,根据墨菲定律,必然有脏数据产生。

    同时需要考虑建立的唯一索引对查询是否真正有帮助,没有帮助的索引可以考虑删除;

    需要考虑多建立的索引对插入性能的影响,根据唯一性相关的数据正确性需求,以及性能需求来权衡是不是需要多建立唯一性索引。

  • 尽量在定长的字段(如: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来查看是否用了索引还是全表扫描。
    • 值分布很稀少的字段不适合建索引,例如“性别”这种只有两三个值的字段。
    • 字符字段不要做主键。
    • 不用外键,由程序保证约束。
    • 使用多列索引时主意顺序和查询条件保持一致,同时删除不必要的单列索引。
    • 删除索引,要做充分论证,最好做数据备份。
support.huaweicloud.com/usermanual-gaussdbformysql/gaussdbformysql_05_0104.html