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

  1. index(a,b,c):
  2. 语句 索引是否发挥作用
  3. Where a=3 是,只使用了a
  4. Where a=3 and b=5 是,使用了a,b
  5. Where a=3 and b=5 and c=4 是,使用了abc
  6. Where b=3 or where c=4
  7. Where a=3 and c=4 a列能发挥索引,c索引也就不能使用了
  8. Where a=3 and b>10 and c=7 A能利用,b能利用, b是一个范围,在这个范围里面的b[10,20]b[20,30]里面都有可能c=7,所以C不能利用
  9. 同上,where a=3 and b like xxxx%’ and c=7 A能用,B能用,C不能用
  10.  
  11. 多列索引经典题目:
  12. http://www.zixue.it/thread-9218-1-4.html
  13.  
  14. 假设某个表有一个联合索引(c1,c2,c3,c4)一下——只能使用该联合索引的c1,c2,c3部分,tree系列里面:c1是有序的,c2c1里面是有序的,c3c2里面是有序的,c4c3里面是有序的。
  15.  
  16. A where c1=x and c2=x and c4>x and c3=x
  17. B where c1=x and c2=x and c4=x order by c3
  18. C where c1=x and c4= x group by c3,c2
  19. D where c1=x and c5=x order by c2,c3
  20. E where c1=x and c2=x and c5=? order by c2,c3
  21.  
  22. create table t4 (
  23. c1 tinyint(1) not null default 0,
  24. c2 tinyint(1) not null default 0,
  25. c3 tinyint(1) not null default 0,
  26. c4 tinyint(1) not null default 0,
  27. c5 tinyint(1) not null default 0,
  28. index c1234(c1,c2,c3,c4)
  29. );
  30. insert into t4 values (1,3,5,6,7),(2,3,9,8,3),(4,3,2,7,5);
  31.  
  32. 对于A:where c1=x and c2=x and c4>x and c3=x
  33. 等价c1=x and c2=x and c3=x and c4>x
  34. 因此 c1,c2,c3,c4都能用上. 如下:
  35.  
  36. mysql> explain select * from t4 where c1=1 and c2=2 and c4>3 and c3=3 \G
  37. id: 1
  38. select_type: SIMPLE
  39. table: t4
  40. type: range //使用索引的方式,使用的是范围索引(c4)
  41. possible_keys: c1234
  42. key: c1234
  43. key_len: 4 //4列#可以看出c1,c2,c3,c4索引都用上
  44. ref: NULL
  45. rows: 1
  46. Extra: Using where
  47.  
  48. 对于B: select * from t4 where c1=1 and c2=2 and c4=3 order by c3
  49. c1 ,c2索引用上了,在c2用到索引的基础上,c3是排好序的,因此不用额外排序,c3,c4没发挥作用.
  50.  
  51. mysql> explain select * from t4 where c1=1 and c2=2 and c4=3 order by c3 \G
  52. id: 1
  53. select_type: SIMPLE
  54. table: t4
  55. type: ref
  56. possible_keys: c1234
  57. key: c1234 //使用了多列索引,但是不一定所有的列都用到了,
  58. key_len: 2 //2列发挥了作用c1c2,
  59. ref: const,const
  60. rows: 1
  61. Extra: Using where
  62. 1 row in set (0.00 sec)
  63.  
  64. mysql> explain select * from t4 where c1=1 and c2=2 and c4=3 order by c5 \G
  65. id: 1
  66. select_type: SIMPLE
  67. table: t4
  68. type: ref
  69. possible_keys: c1234
  70. key: c1234 //多列索引使用到了
  71. key_len: 2 //只是使用到了多列索引中的2列c1c2
  72. ref: const,const
  73. rows: 1
  74. Extra: Using where; Using filesort //Usingfilesort是二次排序,在磁盘或者内存里面,c5是没有顺序的所以取出来之后要排序。
  75.  
  76. D语句:where c1=x and c5=x order by c2,c3C1确定的基础上,c2是有序的,C2之下C3是有序的,因此c2,c3发挥的排序的作用.
  77. 因此,没用到filesort。只能使用一个索引,c2,c3的索引能够用来排序。
  78.  
  79. mysql> explain select * from t4 where c1=1 and c5=2 order by c2,c3 \G
  80. id: 1
  81. select_type: SIMPLE
  82. table: t4
  83. type: ref
  84. possible_keys: c1234 //多列索引使用到了
  85. key: c1234
  86. key_len: 1 //只是使用到了多列索引中的1列c1,
  87. ref: const
  88. rows: 1
  89. Extra: Using where //没有Using filesort的文件排序,因为c2c3是排好序的
  90.  
  91. mysql> explain select * from t4 where c1=1 and c5=2 order by c3 \G
  92. id: 1
  93. select_type: SIMPLE
  94. table: t4
  95. partitions: NULL
  96. type: ref
  97. possible_keys: c1234
  98. key: c1234
  99. key_len: 1
  100. ref: const
  101. rows: 1
  102. filtered: 20.00
  103. Extra: Using index condition; Using where; Using filesort //要排序,因为c3跳过了c2,所以要文件排序(比如国家下面的省,先要国家排序后在省排序。现在跳过国家去排省就要重新排序了),没法利用索引了。
  104.  
  105. E: where c1=x and c2=x and c5=? order by c2,c3
  106. 这一句等价与 elect * from t4 where c1=1 and c2=3 and c5=2 order by c3;
  107. 因为c2的值既是固定的,参与排序时并不考虑
  108.  
  109. mysql> explain select * from t4 where c1=1 and c2=3 and c5=2 order by c2,c3 \G
  110. *************************** 1. row ***************************
  111. id: 1
  112. select_type: SIMPLE
  113. table: t4
  114. type: ref
  115. possible_keys: c1234
  116. key: c1234
  117. key_len: 2 //用到了2列索引,
  118. ref: const,const
  119. rows: 1
  120. Extra: Using where //没有用到文件排序,说明c2c3索引都用到了,
  121.  
  122. mysql> explain select * from t4 where c1=1 and c5=2 order by c2,c3 \G
  123. id: 1
  124. select_type: SIMPLE
  125. table: t4
  126. partitions: NULL
  127. type: ref
  128. possible_keys: c1234
  129. key: c1234
  130. key_len: 1 //用到了1列索引,
  131. ref: const
  132. rows: 1
  133. filtered: 20.00
  134. Extra: Using index condition; Using where //不用排序,因为先根据cw2排序然后根据c3排序,而c2c3是已经排好序的
  135.  
  136. mysql> explain select * from t4 where c1=1 and c5=2 order by c3,c2 \G
  137. id: 1
  138. select_type: SIMPLE
  139. table: t4
  140. partitions: NULL
  141. type: ref
  142. possible_keys: c1234
  143. key: c1234
  144. key_len: 1 //用到了1列索引,
  145. ref: const
  146. rows: 1
  147. filtered: 20.00
  148. Extra: Using index condition; Using where; Using filesort //要排序,因为先根据c3排序再根据c2排序,(比如国家下面的省,先要国家排序后在省排序。现在跳过国家去排省就要重新排序了)
  149.  
  150. mysql> explain select * from t4 where c1=1 and c2=3 and c5=2 order by c3,c2 \G
  151. *************************** 1. row ***************************
  152. id: 1
  153. select_type: SIMPLE
  154. table: t4
  155. partitions: NULL
  156. type: ref
  157. possible_keys: c1234
  158. key: c1234
  159. key_len: 2
  160. ref: const,const
  161. rows: 1
  162. filtered: 20.00
  163. Extra: Using index condition; Using where //没有排序,虽然c3在c2的前面,但是c2是定值。
  164.  
  165. mysql> select cat_id,avg(shop_price) from goods group by cat_id;
  166. +--------+-----------------+
  167. | cat_id | avg(shop_price) |
  168. +--------+-----------------+
  169. | 2 | 823.330000 |
  170. | 3 | 1746.066667 |
  171. | 4 | 2297.000000 |
  172. | 5 | 3700.000000 |
  173. | 8 | 75.333333 |
  174. | 11 | 31.000000 |
  175. | 13 | 33.500000 |
  176. | 14 | 54.000000 |
  177. | 15 | 70.000000 |
  178. +--------+-----------------+
  179.  
  180. mysql> explain select cat_id,avg(shop_price) from goods group by cat_id \G;
  181. id: 1
  182. select_type: SIMPLE
  183. table: goods
  184. partitions: NULL
  185. type: ALL
  186. possible_keys: NULL
  187. key: NULL
  188. key_len: NULL
  189. ref: NULL
  190. rows: 31
  191. filtered: 100.00
  192. Extra: Using temporary; Using filesort //分组操作的时候要先排序,这里Using temporary根据cat_id进行排序,使用的是临时表排序,如果将cat_id加上索引,那么cat_id已经排好序了,就不需要使用临时表来排序。(有可能加了索引还是使用了临时表,那是因为mysql做了自动优化.)
  193.  
  194. mysql> alter table goods add index catid_index(cat_id);
  195.  
  196. 对于C where c1=x and c4= x group by c3,c2
  197. 只用到c1索引,因为group by c3,c2的顺序无法利用c2,c3索引
  198. mysql> explain select * from t4 where c1=1 and c4=2 group by c3,c2 \G
  199. id: 1
  200. select_type: SIMPLE
  201. table: t4
  202. type: ref
  203. possible_keys: c1234
  204. key: c1234
  205. key_len: 1 #只用到c1,因为先用c3后用c2分组,导致c2,c3索引没发挥作用
  206. ref: const
  207. rows: 1
  208. Extra: Using where; Using temporary; Using filesort//并且还要排序
  209.  
  210. mysql> explain select * from t4 where c1=1 and c4=2 group by c2,c3 \G
  211. id: 1
  212. select_type: SIMPLE
  213. table: t4
  214. type: ref
  215. possible_keys: c1234
  216. key: c1234
  217. key_len: 1
  218. ref: const
  219. rows: 1
  220. Extra: Using where
  221. 1 row in set (0.00 sec)
  1. 1.2 hash索引(数据散的放的)
  2. memory表里,默认是hash索引,hash的理论查询时间复杂度为O(1),O(1)是说任意给一行,理论上一次就能够找到。
  3.  
  4. 疑问: 既然hash的查找如此高效,为什么不都用hash索引?
  5. 答:1:hash函数计算后的结果是随机的,如果是在磁盘上放置数据,随机查询是非常慢的。虽然算这行数据在哪里算的很快,但是去取这行数据的时候就很慢。
  6. 比如主键为id为例, 那么随着id的增长, id对应的行,在磁盘上随机放置.
  7.  
  8. 2: 不法对范围查询进行优化,随机的范围查找慢。
  9.  
  10. 3: 无法利用前缀索引. 比如在btree中,field列的值"hellopworld并加索引查询xx=helloword,自然可以利用索引, xx=hello,也可以利用索引(左前缀索引),而利用hash索引,因为hash('helloword')和hash('hello')就是截然不同的结果,所以没法利用前缀优化。
  11.  
  12. 4: 排序也无法利用hash索引来优化.
  13.  
  14. 5: 必须回行.就是说 通过索引拿到数据位置,必须回到表中取数据

mysql优化-----多列索引的左前缀规则的更多相关文章

  1. 【转】MYSQL数据库四种索引类型的简单使用--MYSQL组合索引“最左前缀”原则

    MYSQL数据库索引类型包括普通索引,唯一索引,主键索引与组合索引,这里对这些索引的做一些简单描述: (1)普通索引 这是最基本的MySQL数据库索引,它没有任何限制.它有以下几种创建方式: 创建索引 ...

  2. 转:SQL 索引最左前缀原理

    表结构和索引列 假设数据库中表是这样的:  我们只考虑一张表employees.titles: 索引是(emp_no,title,from_date) SHOW INDEX FROM employee ...

  3. MySQL优化之避免索引失效的方法

    在上一篇文章中,通过分析执行计划的字段说明,大体说了一下索引优化过程中的一些注意点,那么如何才能避免索引失效呢?本篇文章将来讨论这个问题. 避免索引失效的常见方法 1.对于复合索引的使用,应按照索引建 ...

  4. mysql之多列索引

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

  5. 性能测试四十二:sql案例之联合索引最左前缀

    联合索引:一个索引同时作用于多个字段 联合索引的最左前缀: A.B.C3个字段--联合索引 这个时候,可以使用的查询条件有:A.A+B.A+C.A+B+C,唯独不能使用B+C,即最左侧那个字段必须匹配 ...

  6. mysql 优化实例之索引创建

    mysql 优化实例之索引创建 优化前: pt-query-degist分析结果: # Query 23: 0.00 QPS, 0.00x concurrency, ID 0x78761E301CC7 ...

  7. MySQL索引解析(联合索引/最左前缀/覆盖索引/索引下推)

    本节内容: 1)索引基础 2)索引类型(Hash索引.有序数组.B+树) 3)索引的几个常见问题 1)联合索引 2)最左前缀原则 3)覆盖索引 4)索引下推 1. 索引基础 索引对查询的速度有着至关重 ...

  8. Mysql优化系列之索引性能

    实际上,前面的数据类型和表结构设计优化不能算优化,只能算规范,也就是说在设计表的时候,应该且必须做到这些 索引是sql优化的核心部分,在<高性能Mysql>中单独抽出一章讲,也印证了其重要 ...

  9. 0104探究MySQL优化器对索引和JOIN顺序的选择

    转自http://www.jb51.net/article/67007.htm,感谢博主 本文通过一个案例来看看MySQL优化器如何选择索引和JOIN顺序.表结构和数据准备参考本文最后部分" ...

随机推荐

  1. [luoguP2221] [HAOI2012]高速公路(线段树)

    传送门 考虑每一段对答案的贡献 用每一段的左端点来表示当前这一段,那么区间就变成了[1,n-1] 如果询问区间[l,r],其中一个点的位置为x,则它对答案的贡献为(x-l)*(r-x)*s[x](s[ ...

  2. 算法复习——LCT(bzoj2049洞穴勘测)

    题目: Description 辉辉热衷于洞穴勘测.某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连 ...

  3. spring之Annotation

    spring除了提供了@Autowired,还提供了以下几类annotation. 1.@Component, @Repository, @Service, @Controller @Reposito ...

  4. P1582 倒水 (二进制)

    题目描述 一天,CC买了N个容量可以认为是无限大的瓶子,开始时每个瓶子里有1升水.接着~~CC发现瓶子实在太多了,于是他决定保留不超过K个瓶子.每次他选择两个当前含水量相同的瓶子,把一个瓶子的水全部倒 ...

  5. 【kmp+最小循环节】poj 2406 Power Strings

    http://poj.org/problem?id=2406 [题意] 给定字符串s,s=a^n,a是s的子串,求n最大是多少 [思路] kmp中的next数组求最小循环节的应用 例如 ababab ...

  6. 【2018.10.27】CXM笔记

    一个数大约有 $O(\sqrt(n)/log^2(n))$ 个约数. 1. 一个棋盘,每个格子最开始都是白的.可以按一个格子,它马跳(日字跳)能到达的 $8$ 个格子反色(当前格不反色).问有多少种方 ...

  7. 【php wamp的配置】

  8. 安卓解析XML文件

    安卓解析XML文件 主要有三种方式:DOM解析.SAX解析.PULL解析 其中: DOM解析为等XMl文件全部加载后,然后根据需要解析的内容解析出所需的内容数据. SAX解析为从XML文件中执行一行, ...

  9. Objective C语言中nil、Nil、NULL、NSNull的区别

    以下内容是基于搜集整理的网上资料,供参考. nil:指向Objective C语言中对象的空指针,其定义值为(id)0. Nil:指向Objective C语言中类(Class)的空指针,其定义值为( ...

  10. npm 安装vue-cli

    TIP:win10下安装,使用管理员身份进行,否则会有权限限制. 1,安装完成node,node有自带的npm,可以直接在cmd中,找到nodeJs安装的路径下,进行命令行全局安装vue-cli.(n ...