索引优化策略1:索引类型1.1B-tree索引
关注的是:Btree索引的左前缀匹配规则,索引在排序和分组上发挥的作用。注:名叫btree索引,大的方面看都用的二叉树、平衡树。但具体的实现上,各引擎稍有不同。比如,严格的说,NDB引擎,使用的是T-tree。Myisam,innodb中,默认用B-tree索引。凡是tree系列的,可理解为”排好序的、快速查找、的结构”。是排好序的,所以查询某个范围就很快。btree索引的常见误区:在where条件常用的列上都加上索引,
例: where cat_id=3 and price>100 ; //查询第3个栏目,100元以上的商品
误: cat_id上,和, price上都加上索引.
错:只能用上cat_id或Price索引,因为是独立的索引,同时只能用上1个,因为每个索引都是针对整个表建的,而where and查询是在排好序的大范围内再查找小的。(mysql5.6以后做了稍微改进,把多列索引进行merge但是效果不好),因此要使用多列索引。在多列上建立索引后,查询哪个列,索引都将发挥作用:
误: 多列索引上,索引发挥作用,需要满足左前缀要求(btree索引的左前缀规则)B-tree多列索引:
a,b列各加上索引:index(a)和index(b)
Where a=3 and b=5 ,首先根据a查找到a=3的一小段,然后在从这小段中查找b=5的,此时b的索引已经发挥不了作用了。因为b的索引就不是在a的那一小段里面建的。b是针对整个表建的索引。以 index(a,b,c) ,Where a=3 and b=5 and c=4 为例,联合索引是先根据a划分大类(a是有序的),再根据b在a里面划分小的(a里面的b是有序的),在根据c在b里面划分更小的(c在b里面是有序的)。就是这样查找的(这是tree系列的索引和查找方式)。Where b=5 and c=4,索引就用不到了,因为首先是根据a分的大类。现在找b=5的,每一个a的区间都可能有b=5的所以首先排好序的a就进不去。Where a=4 and c=4,a索引用到,c用不到。每段b里面都可能有c=4的。多列索引:左前缀规则,中间断线就不行了。否则只能使用到部分。

index(a,b,c):
语句                                            索引是否发挥作用
Where a=3                                        是,只使用了a列
Where a=3 and b=5                                 是,使用了a,b列
Where a=3 and b=5 and c=4                        是,使用了abc
Where b=3  or  where c=4                        否
Where a=3 and c=4                                a列能发挥索引,c索引也就不能使用了
Where a=3 and b>10 and c=7                        A能利用,b能利用, b是一个范围,在这个范围里面的b[10,20]b[20,30]里面都有可能c=7,所以C不能利用
同上,where a=3 and b like ‘xxxx%’ and c=7        A能用,B能用,C不能用多列索引经典题目:
http://www.zixue.it/thread-9218-1-4.html假设某个表有一个联合索引(c1,c2,c3,c4)一下——只能使用该联合索引的c1,c2,c3部分,tree系列里面:c1是有序的,c2在c1里面是有序的,c3在c2里面是有序的,c4在c3里面是有序的。A where c1=x and c2=x and c4>x and c3=x
B where c1=x and c2=x and c4=x order by c3
C where c1=x and c4= x group by c3,c2
D where c1=x and c5=x order by c2,c3
E where c1=x and c2=x and c5=? order by c2,c3create table t4 (
c1 tinyint(1) not null default 0,
c2 tinyint(1) not null default 0,
c3 tinyint(1) not null default 0,
c4 tinyint(1) not null default 0,
c5 tinyint(1) not null default 0,
index c1234(c1,c2,c3,c4)
);
insert into t4 values (1,3,5,6,7),(2,3,9,8,3),(4,3,2,7,5);对于A:where c1=x and c2=x and c4>x and c3=x,
等价c1=x and c2=x and c3=x and c4>x
因此 c1,c2,c3,c4都能用上. 如下:mysql> explain select * from t4 where c1=1 and c2=2 and c4>3 and c3=3 \Gid: 1select_type: SIMPLEtable: t4type: range   //使用索引的方式,使用的是范围索引(c4)
possible_keys: c1234key: c1234key_len: 4       //4列#可以看出c1,c2,c3,c4索引都用上ref: NULLrows: 1Extra: Using where 对于B: select * from t4 where c1=1 and c2=2 and c4=3 order by c3
c1 ,c2索引用上了,在c2用到索引的基础上,c3是排好序的,因此不用额外排序,c3,c4没发挥作用.mysql> explain select * from t4 where c1=1 and c2=2 and c4=3 order by c3 \Gid: 1select_type: SIMPLEtable: t4type: ref
possible_keys: c1234key: c1234   //使用了多列索引,但是不一定所有的列都用到了,key_len: 2       //2列发挥了作用c1c2,ref: const,constrows: 1Extra: Using where
1 row in set (0.00 sec)mysql> explain select * from t4 where c1=1 and c2=2 and c4=3 order by c5 \Gid: 1select_type: SIMPLEtable: t4type: ref
possible_keys: c1234key: c1234            //多列索引使用到了key_len: 2                //只是使用到了多列索引中的2列c1c2ref: const,constrows: 1Extra: Using where; Using filesort  //Usingfilesort是二次排序,在磁盘或者内存里面,c5是没有顺序的所以取出来之后要排序。D语句:where c1=x and c5=x order by c2,c3,C1确定的基础上,c2是有序的,C2之下C3是有序的,因此c2,c3发挥的排序的作用.
因此,没用到filesort。只能使用一个索引,c2,c3的索引能够用来排序。mysql> explain select * from t4 where c1=1 and c5=2 order by c2,c3 \G  id: 1select_type: SIMPLEtable: t4type: ref
possible_keys: c1234    //多列索引使用到了key: c1234key_len: 1        //只是使用到了多列索引中的1列c1,ref: constrows: 1Extra: Using where     //没有Using filesort的文件排序,因为c2c3是排好序的mysql> explain select * from t4 where c1=1 and c5=2 order by c3 \Gid: 1select_type: SIMPLEtable: t4partitions: NULLtype: ref
possible_keys: c1234key: c1234key_len: 1ref: constrows: 1filtered: 20.00Extra: Using index condition; Using where; Using filesort  //要排序,因为c3跳过了c2,所以要文件排序(比如国家下面的省,先要国家排序后在省排序。现在跳过国家去排省就要重新排序了),没法利用索引了。E: where c1=x and c2=x and c5=? order by c2,c3
这一句等价与 elect * from t4 where c1=1 and c2=3 and c5=2 order by c3;
因为c2的值既是固定的,参与排序时并不考虑mysql> explain select * from t4 where c1=1 and c2=3 and c5=2 order by c2,c3 \G
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: t4type: ref
possible_keys: c1234key: c1234key_len: 2                //用到了2列索引,ref: const,constrows: 1Extra: Using where    //没有用到文件排序,说明c2c3索引都用到了,mysql> explain select * from t4 where c1=1 and c5=2 order by c2,c3 \Gid: 1select_type: SIMPLEtable: t4partitions: NULLtype: ref
possible_keys: c1234key: c1234key_len: 1            //用到了1列索引,ref: constrows: 1filtered: 20.00Extra: Using index condition; Using where    //不用排序,因为先根据cw2排序然后根据c3排序,而c2c3是已经排好序的mysql>  explain select * from t4 where c1=1 and c5=2 order by c3,c2 \Gid: 1select_type: SIMPLEtable: t4partitions: NULLtype: ref
possible_keys: c1234key: c1234key_len: 1        //用到了1列索引,ref: constrows: 1filtered: 20.00Extra: Using index condition; Using where; Using filesort  //要排序,因为先根据c3排序再根据c2排序,(比如国家下面的省,先要国家排序后在省排序。现在跳过国家去排省就要重新排序了)mysql> explain select * from t4 where c1=1 and c2=3 and c5=2 order by c3,c2 \G
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: t4partitions: NULLtype: ref
possible_keys: c1234key: c1234key_len: 2ref: const,constrows: 1filtered: 20.00Extra: Using index condition; Using where   //没有排序,虽然c3在c2的前面,但是c2是定值。mysql> select cat_id,avg(shop_price) from goods group by cat_id;
+--------+-----------------+
| cat_id | avg(shop_price) |
+--------+-----------------+
|      2 |      823.330000 |
|      3 |     1746.066667 |
|      4 |     2297.000000 |
|      5 |     3700.000000 |
|      8 |       75.333333 |
|     11 |       31.000000 |
|     13 |       33.500000 |
|     14 |       54.000000 |
|     15 |       70.000000 |
+--------+-----------------+

mysql> explain select cat_id,avg(shop_price) from goods group by cat_id \G;id: 1select_type: SIMPLEtable: goodspartitions: NULLtype: ALL
possible_keys: NULLkey: NULLkey_len: NULLref: NULLrows: 31filtered: 100.00Extra: Using temporary; Using filesort   //分组操作的时候要先排序,这里Using temporary根据cat_id进行排序,使用的是临时表排序,如果将cat_id加上索引,那么cat_id已经排好序了,就不需要使用临时表来排序。(有可能加了索引还是使用了临时表,那是因为mysql做了自动优化.)mysql> alter table goods add index catid_index(cat_id);对于C where c1=x and c4= x group by c3,c2
只用到c1索引,因为group by c3,c2的顺序无法利用c2,c3索引
mysql> explain select * from t4 where c1=1 and c4=2 group by c3,c2 \Gid: 1select_type: SIMPLEtable: t4type: ref
possible_keys: c1234key: c1234key_len: 1             #只用到c1,因为先用c3后用c2分组,导致c2,c3索引没发挥作用ref: constrows: 1Extra: Using where; Using temporary; Using filesort//并且还要排序mysql> explain select * from t4 where c1=1 and c4=2 group by c2,c3 \Gid: 1select_type: SIMPLEtable: t4type: ref
possible_keys: c1234key: c1234key_len: 1ref: constrows: 1Extra: Using where
1 row in set (0.00 sec)

1.2 hash索引(数据散的放的)
在memory表里,默认是hash索引,hash的理论查询时间复杂度为O(1),O(1)是说任意给一行,理论上一次就能够找到。疑问: 既然hash的查找如此高效,为什么不都用hash索引?
答:1:hash函数计算后的结果是随机的,如果是在磁盘上放置数据,随机查询是非常慢的。虽然算这行数据在哪里算的很快,但是去取这行数据的时候就很慢。
比如主键为id为例, 那么随着id的增长, id对应的行,在磁盘上随机放置.2: 不法对范围查询进行优化,随机的范围查找慢。3: 无法利用前缀索引. 比如在btree中,field列的值"hellopworld并加索引查询xx=helloword,自然可以利用索引, xx=hello,也可以利用索引(左前缀索引),而利用hash索引,因为hash('helloword')和hash('hello')就是截然不同的结果,所以没法利用前缀优化。4: 排序也无法利用hash索引来优化.5: 必须回行.就是说 通过索引拿到数据位置,必须回到表中取数据

mysql优化-----多列索引的左前缀规则相关推荐

  1. mysql索引最左前缀原则

    mysql索引最左前缀原则 创建索引可以大大提高系统的性能. 第一,通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性. 第二,可以大大加快数据的检索速度,这也是创建索引的最主要的原因. 第三, ...

  2. 原创:史上最全最通俗易懂的,索引最左前缀匹配原则(认真脸)

    索引最左前缀匹配原则 对于最左前缀匹配原则居然没有百度百科,实在是让我感觉不可思议. 最左前缀匹配原则,用几句话来概述就是: 顾名思义,就是最左优先,在创建多列索引时,要根据业务需求,where子句中 ...

  3. mysql之多列索引

    mysql的多列索引是经常会遇到的问题,怎样才能有效命中索引,是本文要探讨的重点. 多列索引使用的Btree,也就是平衡二叉树.简单来说就是排好序的快速索引方式.它的原则就是要遵循左前缀索引. 多个索 ...

  4. mysql中组合索引创建的原则是什么意思_面试前必须要掌握的MySQL索引最左前缀匹配原则...

    在面试中,经常会遇到这种问题,如果我们设置联合索引的顺序是(a, b, c), 那么如果我们在查询时的顺序却是(a, c, b) 会走索引吗?这个问题被问到的频率之高,令人乍舌,在这篇文章中,我们就深 ...

  5. MySQL优化篇:索引

    文章目录 1.概念 1.1 是什么 1.2 优缺点 2.MySQL的索引 2.1 Btree索引 2.2 B+Tree索引 3.MySQL索引分类 3.1 单值索引(普通索引) 3.2 唯一索引 3. ...

  6. mysql 分段执行_19个MySQL优化技巧,索引优化这样做最有效!

    - 点击上方"中国统计网"订阅我吧!- 声明:下面的优化方案都是基于" Mysql-索引-BTree类型 "01善用EXPLAIN 做MySQL优化,我们要善用 ...

  7. mysql优化器放弃索引场景,MYSQL索引优化(索引失效场景)

    学习mysql是作为一名Java工程师必不可少的事情,但是我们只认识mysql的增删查改建表等等的sql语句其实远远不够的,对于进阶mysql来说,索引是一个很重要的部分.下面我们就来说一下在mysq ...

  8. 【MySQL 优化】单一索引与复合索引

    MySQL 单一索引与复合索引 前 言 一.索引的最左前缀匹配原则 二.使用使用联合索引优势 1. 减少开销 2. 覆盖索引 3. 效率高 前 言 单一索引是指索引列为一列的情况,即新建索引的语句只实 ...

  9. 覆盖索引最左前缀原则索引下推

    覆盖索引 如果执行的语句是 select ID from T where k between 3 and 5,这时只需要查 ID 的值,而 ID 的值已经在 k 索引树上了,因此可以直接提供查询结果, ...

最新文章

  1. 2018年4月份,阿里最新的java程序员面试题目
  2. 海康、大华摄像头网页无插件直播监控流媒体服务EasyNVR使用web和安卓浏览器能正常使用,苹果手机无法打开问题解决
  3. 节能与新能源汽车技术路线图2.0_节能与新能源汽车技术路线图(2.0版)
  4. linux运行c程序a. out,bash:./a.out:在由ld生成的运行可执行文件上没有这样的文件或目录。...
  5. php创建分页类,一个最强的PHP通用分页类
  6. 深度学习(Deep Learning)读书思考三:正则化
  7. [ZT]比尔·盖茨被激怒 微软肩负起唱衰Google的使命
  8. day25 java的集合(2)collection
  9. es 根据_id查询_京东把 Elasticsearch 用得真牛逼!日均5亿订单查询完美解决
  10. OpenAI挑战DOTA 2世界冠军OG,这是赌上人类尊严的决战
  11. 0c-36-自动释放池应用场景
  12. HDU2014 青年歌手大奖赛_评委会打分【入门】
  13. cocos3 开篇helloworld
  14. 乐视路由器刷机后修改固件成art信息
  15. 教你制作一张漂亮的城市分布图 比如加油站分布地图
  16. 使用Lucene对doc、docx、pdf、txt文档进行全文检索功能的实现
  17. matlab中如何用数组绘图,matlab 基础学习(1)——数组,矩阵操作和绘图基础学习...
  18. Windows构建Flutter环境,无法访问maven.google.com
  19. mysql extendedstatus_mysqladmin的extended-status指令查看 mysql各状态
  20. centos7虚拟机忘记密码

热门文章

  1. SAP MM 初阶之供应商寄售采购模式下ERS功能的测试
  2. SAP独门神器之VC变式配置,硬核整理版重磅推出!
  3. SAP PM设备主记录
  4. SAP Web Intelligence初探
  5. BERT在小米NLP业务中的实战探索
  6. ICLR 2019论文解读:量化神经网络
  7. 深度学习已入末路,谁能引领下一代AI?
  8. 英国更注重人工智能基础性研究
  9. 2019需要关注的几大AI趋势
  10. SAP MM 物料主数据里某字段看不到就是屏幕格式设置导致的?