设为首页 收藏本站
查看: 868|回复: 0

[经验分享] mysql 多列索引的生效规则

[复制链接]

尚未签到

发表于 2017-12-12 10:47:35 | 显示全部楼层 |阅读模式
  mysql中 myisam,innodb默认使用的是 Btree索引,至于btree的数据结构是怎样的都不重要,
  只需要知道结果,既然是索引那这个数据结构最后是排好序;就像新华字典他的目录就是按照a,b,c..这样排好序的;
  所以你在找东西的时候才快,比如你找 “中” 这个字的解释,你肯定就会定位到目录的 z 开头部分;
  组合索引可以这样理解,比如(a,b,c),abc都是排好序的,在任意一段a的下面b都是排好序的,任何一段b下面c都是排好序的;
DSC0000.png

  组合索引的生效原则是  从前往后依次使用生效,如果中间某个索引没有使用,那么断点前面的索引部分起作用,断点后面的索引没有起作用;
  比如
  

where a=3 and b=45 and c=5 .... 这种三个索引顺序使用中间没有断点,全部发挥作用;  

where a=3 and c=5... 这种情况下b就是断点,a发挥了效果,c没有效果  

where b=3 and c=4... 这种情况下a就是断点,在a后面的索引都没有发挥作用,这种写法联合索引没有发挥任何效果;  

where b=45 and a=3 and c=5 .... 这个跟第一个一样,全部发挥作用,abc只要用上了就行,跟写的顺序无关  

  (a,b,c) 三个列上加了联合索引(是联合索引 不是在每个列上单独加索引)
  还需注意,  (a,b,c)多列索引和 (a,c,b)是不一样的,看上面的图也看得出来关系顺序是不一样的;
  分析几个实际例子来加强理解;
  分析句子中使用的索引情况
  

(0)    select * from mytable where a=3 and b=5 and c=4;  
abc三个索引都在where条件里面用到了,而且都发挥了作用
  
(
1)    select * from mytable where  c=4 and b=6 and a=3;  
这条语句列出来只想说明 mysql没有那么笨,where里面的条件顺序在查询之前会被mysql自动优化,效果跟上一句一样
  
(
2)    select * from mytable where a=3 and c=7;  
a用到索引,b没有用,所以c是没有用到索引效果的
  
(
3)    select * from mytable where a=3 and b>7 and c=3;  
a用到了,b也用到了,c没有用到,这个地方b是范围值,也算断点,只不过自身用到了索引
  
(
4)    select * from mytable where b=3 and c=4;  
因为a索引没有使用,所以这里 bc都没有用上索引效果
  
(
5)    select * from mytable where a>4 and b=7 and c=9;  
a用到了  b没有使用,c没有使用
  
(
6)    select * from mytable where a=3 order by b;  
a用到了索引,b在结果排序中也用到了索引的效果,前面说了,a下面任意一段的b是排好序的
  
(
7)    select * from mytable where a=3 order by c;  
a用到了索引,但是这个地方c没有发挥排序效果,因为中间断点了,使用 explain 可以看到 filesort
  
(
8)    select * from mytable where b=3 order by a;  
b没有用到索引,排序中a也没有发挥索引效果
  

  补充一个:
  快速生成1000W测试数据库;
  创建测试表:
  

create table user (  
id
int(10) not null auto_increment,  
uname  
varchar(20) ,  
regtime  
char(30)  ,  
age  
int(11)   ,  

primary key (id)  
)  
  
engine
=myisam default charset=utf8 collate=utf8_general_ci  ,  
auto_increment
=1 ;  

  编写存储过程:
  

delimiter $$  

SET AUTOCOMMIT = 0$$  

  

create  procedure test()  

begin  
declare v_cnt decimal (10)  default 0 ;
  
dd:loop
  
insert  into user values
  
(null,rand()*10,now(),rand()*50),
  
(null,rand()*10,now(),rand()*50),
  
(null,rand()*10,now(),rand()*50),
  
(null,rand()*10,now(),rand()*50),
  
(null,rand()*10,now(),rand()*50),
  
(null,rand()*10,now(),rand()*50),
  
(null,rand()*10,now(),rand()*50),
  
(null,rand()*10,now(),rand()*50),
  
(null,rand()*10,now(),rand()*50),
  
(null,rand()*10,now(),rand()*50);
  
commit;
  
set v_cnt = v_cnt+10 ;
  
if  v_cnt = 10000000 then leave dd;
  
end if;
  
end loop dd ;
  
end;$$
  

  
delimiter ;
  

  调用存储过程:
  

call test();  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-423279-1-1.html 上篇帖子: 分享几款常用的MySQL管理工具 下篇帖子: MySQL必知必会笔记
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表