`
annan211
  • 浏览: 445889 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

MySQL松散索引扫描与紧凑索引扫描

阅读更多

在优化group by查询的时候,一般的会想到两个名词:松散索引扫描(Loose Index Scan)和紧凑索引扫描(Tight Index Scan),因为通过这两种索引扫描就可以高效快速弟完成group by操作。
  请尊重知识,请尊重原创 更多资料参考请见  http://www.cezuwang.com/listFilm?page=1&areaId=906&filmTypeId=1
在group by操作在没有合适的索引可用的时候,通常先扫描整个表提取数据并创建一个临时表,然后按照group by指定的列进行排序。在这个临时表里面,对于每一个group的数据行来说是连续在一起的。完成排序之后,就可以发现所有的groups,并可以执行聚集函数(aggregate function)。可以看到,在没有使用索引的时候,需要创建临时表和排序。

MySQL建立的索引(B+Tree)通常是有序的,如果通过读取索引就完成group by操作,那么就可避免创建临时表和排序。因而使用索引进行group by的最重要的前提条件是所有group by的参照列(分组依据的列)来自于同一个索引,且索引按照顺序存储所有的keys(即BTREE index,而HASH index没有顺序的概念)。

MySQ有两种索引扫描方式完成group by操作,就是上面提到的松散索引扫描和紧凑索引扫描。在松散索引扫描方式下,分组操作和范围预测(如果有的话)一起执行完成的。在紧凑索引扫描方式下,先对索引执行范围扫描(range scan),再对结果元组进行分组。

松散索引扫描(Loose Index Scan)

松散索引扫描相当于Oracle中的跳跃索引扫描(skip index scan),就是不需要连续的扫描索引中得每一个元组,扫描时仅考虑索引中得一部分。当查询中没有where条件的时候,松散索引扫描读取的索引元组的个数和groups的数量相同。如果where条件包含范围预测,松散索引扫描查找每个group中第一个满足范围条件,然后再读取最少可能数的keys。松散索引扫描只需要读取很少量的数据就可以完成group by操作,因而执行效率非常高。使用松散索引扫描需要满足以下条件:

1、查询在单一表上。

2、group by指定的所有列是索引的一个最左前缀,并且没有其它的列。比如表t1( c1,c2,c3,c4)上建立了索引(c1,c2,c3)。如果查询包含“group by c1,c2”,那么可以使用松散索引扫描。但是“group by c2,c3”(不是索引最左前缀)和“group by c1,c2,c4”(c4字段不在索引中)。

3、如果在选择列表select list中存在聚集函数,只能使用 min()和max()两个聚集函数,并且指定的是同一列(如果min()和max()同时存在)。这一列必须在索引中,且紧跟着group by指定的列。比如,select t1,t2,min(t3),max(t3) from t1  group by c1,c2。

4、如果查询中存在除了group by指定的列之外的其他部分,那么必须以常量的形式出现(除了min()和max()两个聚集函数)。

比如,select c1,c3 from t1 group by c1,c2不能使用松散索引扫描。而select c1,c3 from t1 where c3 =  3 group by c1,c2可以使用松散索引扫描。

5、索引中的列必须索引整个数据列的值(full column values must be indexed),而不是一个前缀索引。比如,c1 varchar(20), INDEX (c1(10)),这个索引没发用作松散索引扫描。

自从5.5开始,松散索引扫描可以作用于在select list中其它形式的聚集函数,除了min()和max()之外,还支持:

1、AVG(DISTINCT), SUM(DISTINCT)和COUNT(DISTINCT)可以使用松散索引扫描。AVG(DISTINCT), SUM(DISTINCT)只能使用单一列作为参数。而COUNT(DISTINCT)可以使用多列参数。

2、在查询中没有group by和distinct条件。

3、之前声明的松散扫描限制条件同样起作用。

紧凑索引扫描(Tight Index Scan)

紧凑索引扫描可能是全索引扫描或者范围索引扫描,取决于查询条件。当松散索引扫描条件没有满足的时候,group by仍然有可能避免创建临时表。如果在where条件有范围扫描,那么紧凑索引扫描仅读取满足这些条件的keys(索引元组)。否则执行索引扫描。因为这种方式读取所有where条件定义的范围内的keys,或者扫描整个索引当没有where条件,因而称作紧凑索引扫描。对于紧凑索引扫描,只有在所有满足范围条件的keys被找到之后才会执行分组操作。

如果紧凑索引扫描起作用,那么必须满足:在查询中存在常量相等where条件字段(索引中的字段),且该字段在group by指定的字段的前面或者中间。来自于相等条件的常量能够填充搜索keys中的gaps,因而可能构成一个索引的完整前缀。索引前缀能够用于索引查找。如果要求对group by的结果进行排序,并且查找字段有可能组成一个索引前缀,MySQL同样可以避免额外的排序操作,因为对有序的索引进行的查找已经按照顺序提取所有的keys。

c2在c1,c3之前,c2=‘a’填充这个坑,组成一个索引前缀,因而能够使用紧凑索引扫描。

select c1,c2,c3 from t1 where c2 = ‘a’ group by c1,c3

c1在索引的最前面,c1=a和group by c2,c3组成一个索引前缀,因而能够使用紧凑索引扫描。

select c1,c2,c3 from t1 where c1 = ‘a’ group by c2,c3
  请尊重知识,请尊重原创 更多资料参考请见  http://www.cezuwang.com/listFilm?page=1&areaId=906&filmTypeId=1
松散索引扫描个紧凑索引扫描的最大区别是是否需要扫描整个索引或者整个范围扫描。
引自 http://www.tuicool.com/articles/fIF3ey

 

分享到:
评论

相关推荐

    MySQL优化GROUP BY(松散索引扫描与紧凑索引扫描)

    主要介绍了MySQL优化GROUP BY(松散索引扫描与紧凑索引扫描),需要的朋友可以参考下

    mysql 松散的索引扫描(Loose index scan)

    历史上MySQL不能做松散的索引扫描,这种方式可以扫描索引的非连续部分,假定下面的例子中,在列(a,b)上有一索引,要运行下面的查询: mysql> SELECT … FROM tbl WHERE b BETWEEN 2 AND 3; 因为索引从列a开始,但是...

    mysql-常见问题,索引优化

    mysql日常使用过程中遇到的问题,以及解决办法,包括discount的bug,avg(null),紧凑索引,松散索引,以及索引优化

    高性能MySQL(第3版).part2

    6.5.7松散索引扫描229 6.5.8最大值和最小值优化231 6.5.9在同一个表上查询和更新232 6.6查询优化器的提示(hint)232 6.7优化特定类型的查询236 6.7.1优化COUNT()查询236 6.7.2优化关联查询239 6.7.3优化子...

    MySQL中distinct语句的基本原理及其与group by的比较

    同样可以通过松散索引扫描或者是紧凑索引扫描来实现,当然,在无法仅仅使用索引即能完成 DISTINCT 的时候,MySQL 只能通过临时表来完成。但是,和 GROUP BY 有一点差别的是,DISTINCT 并不需要进行排序。也就是说,...

    MySQL DISTINCT 的基本实现原理详解

    同样可以通过松散索引扫描或者是紧凑索引扫描来实现,当然,在无法仅仅使用索引即能完成 DISTINCT 的时候,MySQL 只能通过临时表来完成。 但是,和 GROUP BY 有一点差别的是,DISTINCT 并不需要进行排序。也就是说,...

    MySQL分组查询Group By实现原理详解

    由于GROUP BY 实际上也同样会进行排序操作,而且与ORDER BY 相比,GROUP BY 主要只是多了排序之后的分组操作。当然,如果在分组的时候还使用了其他的一些聚合函数,那么还需要一些聚合函数... 何谓松散索引扫描实现 G

    MySQL中distinct与group by语句的一些比较及用法讲解

    在数据表中记录了用户验证时使用的...所以,DISTINCT 的实现和 GROUP BY 的实现也基本差不多,没有太大的区别,同样可以通过松散索引扫描或者是紧凑索引扫描来实现。    那DISTINCT 和GROUP BY哪个效率更高?  

    MySQL优化GROUP BY方案

    松散索引扫描 1.满足条件  查询针对一个表。  GROUP BY 使用索引的最左前缀。  只可以使用MIN()和MAX()聚集函数,并且它们均指向相同的列。 2.示例 表t1(c1,c2,c3,c4) 有一个索引 idx(c1,c2,c3):

    mongodb-java:模仿monogdb写一个数据库

    与MySQL对比```````````` [](#mongodb-文档) [mongoDB ](#mongodb-可视化管理工具) 空间索引 导出,导入,运行时备份 Fsync锁,数据修复 用户管理,安全认证 主从复制 副本集(复制) 分片 学习MongoDB 练习环境 MongoDB v...

Global site tag (gtag.js) - Google Analytics