zoukankan      html  css  js  c++  java
  • 【mysql】之聊聊sql索引使用的规则

    看这篇文章建议先看 Explain分析SQL性能

    建表SQL

    -- 建表
    CREATE TABLE `sys_user` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `v_name` varchar(20) DEFAULT '' COMMENT '姓名',
      `age` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '年龄',
      `pos` varchar(20) NOT NULL DEFAULT '' COMMENT '职位',
      `add_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '入职时间',
      PRIMARY KEY (`id`),
      KEY `idx_name_age_pos` (`v_name`,`age`,`pos`)
    ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COMMENT='员工记录表';
    
    -- 建索引
    ALTER TABLE sys_user ADD INDEX idx_name_age_pos(`v_name`, age, pos);

    1、全值匹配,最优

    image

    第一个key_len=63,计算规则,v_name varchar(20),20*3+2(动态列类型)+1(允许为NULL)=63

    第二个key_len=67,计算规则 v_name+age 长度,63+4(int,不允许为NULL)=67

    第三个key_len=129,计算规则,v_name+age+pos,63+4+(20*3+2)=129

    2、最佳左前缀(如果建立了联合索引,指的是从索引的最左前列开始并且不跳过索引中的列

    image

    我们建表索引是idx_name_age_pos,sql1和sql2都没有使用到索引,而sql3没有遵循左匹配也使用到索引,是因为使用了覆盖索引,

    覆盖索引:当使用覆盖索引的方式,select id,v_name,age from sys_user where age=10(where后面没有其他没有索引的字段条件),即使不是以v_name开头,也会使用联合索引,总结来说就是

    select 后的字段有索引,where字段也有索引,则无关执行顺序,不需要最左边前缀法则

     

    3、不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描

    image

    image

    4、索引不能使用索引中范围条件右边的列

    image

    我们发现sql4和sql2使用的索引是一致的,sql4的pos索引没有用到,说明了范围右边的索引列示法使用到

    5、尽量使用覆盖索引,提高查询效率,避免使用select *

    6、mysql使用 !=,<>的时候无法使用索引会导致全表扫描

    image

    7、mysql的is null可以使用索引,is not null 无法使用索引

    image

    8、like以通配符开头('%abc...')mysql索引失效会变成全表扫描的操作

    image

    解决like ‘%%’无法使用索引的问题

    image

    9、字符串不加单引号,导致索引失效

    image

    10、使用or导致索引字段失效

    image

    总结:

    假设有索引index a_b_c(`a`,`b`,`c`)

    where语句

    索引是否被使用

    where a = 3 a
    where a = 3 and b = 5 a,b
    where a = 3 and b = 5 and c = 4 a,b,c
    where b = 3 或者 where b = 3 and c = 4  或者 where c = 4 没有使用索引
    where a = 3 and c = 5 a,因为b中断,所以c索引无法使用
    where a = 3 and b > 4 and c = 5 a,b,因为c在范围索引之后,所以无法使用
    where a = 3 and b like 'kk%' and c = 4 a,b,c
    where a = 3 and b like '%kk' and c = 4 a
    where a = 3 and b like '%kk%' and c = 4 a
    where a = 3 and b like 'k%kk%' and c = 4 a,b,c

    1、对于单键索引,尽量选择针对当前query过滤性更好的索引

    2、在选择组合索引的时候,当前Query中过滤性最好的字段在索引字段顺序中,位置越靠前越好。(避免索引过滤性好的索引失效)

    3、在选择组合索引的时候,尽量选择可以能够包含当前query中的where字句中更多字段的索引

    4、尽可能通过分析统计信息和调整query的写法来达到选择合适索引的目的

  • 相关阅读:
    Oracle 单引号与双引号的区别
    oracle 生成随机数
    oracle 表空间及查看所有用户的表空间
    字节和字符的区别
    java io
    Oracle 基础
    gvim 常用键
    Python之struct
    Python之MySQLdb
    Python之sqlite3
  • 原文地址:https://www.cnblogs.com/gyjx2016/p/12462536.html
Copyright © 2011-2022 走看看