- 索引值
- 只要列中包含有NULL值都将不会被包含在索引中,多列索引中只要有一列含有 NULL 值,那么这一列对于此多列索引就是无效的。所以我们在数据库设计时,应该为字段设置 NOT NULL 约束,或着设置非 NULL 的默认值。
- 字符类型务必加上引号,若varchar类型字段值不加单引号,可能会发生数据类型隐式转化,自动转换为int型,使索引无效。
- 不在索引字段上进行计算、函数、类型转换(自动\手动),防止导致索引失效,执行全表扫描
- 定义
- 尽量的扩展索引,非必要不新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可。
- 建联合索引的时候,区分度最高的字段在最左边。
- 业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引。虽然唯一索引会影响insert速度,但是对于查询的速度提升是非常明显的。另外,即使在应用层做了非常完善的校验控制,只要没有唯一索引,在并发的情况下,依然有脏数据产生。
- 区分度
- 更新频繁的字段上不建立索引。因为更新操作会变更B+树,重建索引,这个过程是十分消耗数据库性能的。
- 区分度不大的字段上不宜建立索引。类似于性别这种区分度不大的字段,建立索引的意义不大。因为不能有效过滤数据,性能和全表扫描相当。
- 尽量选择区分度高的列作为索引,区分度的公式是count(distinct col)/count(*),表示字段不重复的比例,比例越大我们扫描的记录数越少,唯一键的区分度是1,而一些状态、性别字段可能在大数据面前区分度就是0
- 尽可能使用短索引。如果对字符串列进行索引,应该指定一个前缀索引。较小的索引涉及的磁盘 IO 较少,较短的值比较起来更快。更为重要的是,对于较短的键值,索引高速缓存中的块能容纳更多的键值,因此,MySQL 也可以在内存中容纳更多的值。这样就增加了找到行而不用读取索引中较多块的可能性。
- 查询条件
- 模糊查询(Like)查询,左侧尽量不要加%
- 负向条件查询不能使用索引(!=、<>、not in、not exists、not like等),可以优化为in查询,但是前提是区分度要高,返回数据的比例在30%以内
- 尽量将范围查询字段放在最后(放在最后联合索引使用最充分,放在中间联合索引使用不充分)。使用联合索引时范围列(当前范围列索引生效)后面的索引列无法生效,同时索引最多用于一个范围列,如果查询条件中有多个范围列,也只能用到一个范围列索引。
- 当OR左右查询字段只有一个是索引,会使该索引失效,只有当OR左右查询字段均为索引列时,这些索引才会生效。索引改为使用 唯一索引(UNION)效率高。
- 查询记录的时候,不要使用 SELECT * FROM,只取需要的数据,尽量只利用索引覆盖,可以减少回表操作,提升效率
- 单表查询时,保证 WHERE 查询条件的顺序和个数与索引建立的顺序和个数要保持一致
- 遵循最左匹配原则,即where的查询条件尽量要从索引的列的最左列开始并且不跳过索引中的列
- 多表关联查询时,保证被关联的字段需要有索引
注
- 当全表扫描速度比索引速度快时,MySQL会使用全表扫描,此时索引失效。
- 如果某个数据列包含许多重复的内容,为它建立索引就没有太大的实际效果