访问方法是什么?
查询语句本质上是声明式的语法,具体的执行方式有很多种。设计mysql的大叔根据不同场景划分了很多种访问方法。
有什么?
- const
- ref
- ref_or_null
- range
- index
- all
- index_merge
- 索引合并
- Intersection索引合并
- Union
- Sort-Union
下面将逐一说明这些访问方法
访问方法:
1.const:
通过主键或唯一二级索引(注意是唯一二级索引)列与一个常数的等值比较时来定位到一条记录的访问方法称为const(意思是常数级别的,代价是可以忽略的)。
例如:select * from table where key2 = 344;此处key2为唯一2级索引。
如果主键或唯一二级索引由多个列构成,则只有在索引列中的每一个列都与常数进行等值比较时,这个const访问方法才有效。
注:
对于唯一二级索引来说,查询列为null值时,比较特殊,不会限制null值的数量,所以可能访问到多条记录,因此时不可以用const访问方法来执行(采取什么方法后面再说)。
2.ref
将某个普通的二级索引列与常数进行等值比较。
例如:select * from table where key1 = 'abc';此处key1为普通二级索引
那么对应的扫描区间就是['abc','abc'],这也是单点扫描区间,可以定位到key1 = ‘abc’的第一条记录,然后沿着记录所在的单相链表向后扫描,直到某条不符合key1 = abc的条件为止,每次获取的二级索引记录,都需要根据此记录进行回表操作,在聚簇索引中找到完整的用户记录在发送给客户局端。
注:此处和const的不同之处在于索引列与常数的比较中可能会匹配多条记录,而const最多只有1条记录。
- 在执行包含"key IS NULL"形式的搜索条件的查询时,最多只能ref访问方法,而不能使用const访问方法
- 对于索引列包含多个列的二级索引来说,只要最左边连续的列是与常数进行进行等值比较都可以
例:select * from table where key_part1 = 'abc' AND key_part2 = 'dwdw';此处key_part1 与key_part2创建的联合索引。
3.ref_or_null
不仅想找出某个二级索引列的值等于某个常数的记录而且还想把该列中值为null得也找出来
列:select * from table where key1 = 'abc' OR key1 IS NULL;
当使用二级索引而不是全屏扫描的时候那么对应的扫描区间就是[null,null]以及['abc','abc'],他会比ref方法多扫描一些值为NULL的二级索引记录。(值为null的记录会放在索引的最左边)
4.range
使用索引执行查询时,对应的扫描区间为若干个单点扫描区间或者范围区间的访问方法叫range
注:(-无穷,+无穷)不能成为range方法。
例:select * from table where key2 IN (1608,3208) OR (key2 >= 38 AND key2 <= 78);
那么扫描区间就是[1608,1608],[3208,3208],[38,78].
5.index
覆盖索引的方式,所查询的列为建立二级索引的列,但是它的查询条件并非最左边的索引的列,那么在这种情况下,如果是select *那么可能走全盘扫描的方式,但是他是select key1,key2,key3,它就会直接便利二级索引找到key2 = 123的列。相对于全盘扫描来说成本会小很多
原因:二级索引比聚簇索引记录会小很多,而且过程也不需要回表,所查的列都在二级索引中,
例:select key1,key2,key3 where key2= 123;index idx_key1_key2_key3(key1,key2,key3)建立联合索引
6.all
全表扫描,不多说。从第一页一条一条往后找。
索引合并
一般情况下,mysql只会为单个索引生产扫描区间
1.Intersection索引合并
针对于AND来说的,当and前后的索引列的搜索范围的主键是递增的,那么就会取两个索引列中主键相同的部分来进行回表,快速定位信息。注:前提是两个索引中主键是递增的。
例:select * from table where key1 = 'a' AND key3 = ‘b’;其中都为key1,key2分别建立二级索引。
为什么需要主键排序?
- 从两个有序集合中取交集比无需集合中容易
- 如果获取到的id(主键)是有序的,那么根据id值执行回表操作就不再是单纯的随机I/O,从而提高效率
2.Union索引合并
那么针对于or来说的,与前一个类似,只不过上面是取交集,这是去重,去掉重复的。要求:依旧是主键要递增。
例:select * from table where key1 = 'a' OR key3 = ‘b’;
如果以任意一个索引扫描区间都为(-无穷,+无穷)。但是索引合并,就会同时查找id,去掉重复的再回表。
3.sort-Union合并
对于select * from table where key1 < 'a' OR key3 > ‘z’;来说两个条件非常诱人,但是又不能走union合并,因为在key1<'a'的范围内id是不连续的。
但是可以这样:
- 先从两个键条中找出二级索引记录,并且分别将二级索引记录按主键排好序,再进行union索引合并。