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

转载 2016年06月02日 12:43:59

在优化group by查询的时候,一般的会想到两个名词:松散索引扫描(Loose Index Scan)和紧凑索引扫描(Tight Index Scan),因为通过这两种索引扫描就可以高效快速弟完成group by操作。

在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

松散索引扫描个紧凑索引扫描的最大区别是是否需要扫描整个索引或者整个范围扫描。

相关文章推荐

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

满足GROUP BY子句的最一般的方法是扫描整个表并创建一个新的临时表,表中每个组的所有行应为连续的,然后使用该临时表来找到组并应用累积函数(如果有)。在某些情况中,MySQL能够做得更好,即通过索引...
  • zm2714
  • zm2714
  • 2012年08月20日 16:51
  • 20598

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

转自:http://blog.csdn.net/zm2714/article/details/7887093 满足GROUP BY子句的最一般的方法是扫描整个表并创建一个新的临时表,...

mysql查询优化以及索引使用

如果应用程序使用了mysql,其中包含一些查询速度慢的sql,我们要去优化它们,优化的思路需要如何进行呢?主要是以下两点: 1、应用程序是否在检索大量超过需要的数据(行、列); 2、mysql...

Mysql索引的使用-组合索引+跳跃条件

关于MYSQL组合索引的使用,官方对下面的例子的说法是可以使用索引: KEY(key_part1,key_part2,key_part3) select .... from table whe...

EasyEclipse for PHP运行PHP文件(关于PHP Browser的配置)

apache/mysql的配置和easyeclipse关系不大。

MySQL 5.6的72个新特性(译)

MySQL 5.6的72个新特性(译) 一,安全提高 1.提供保存加密认证信息的方法,使用.mylogin.cnf文件。使用mysql_config_edi...

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

官网:http://dev.mysql.com/doc/refman/5.5/en/group-by-optimization.html        满足GROUP BY子句的最一般的方法是...

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

满足GROUP BY子句的最一般的方法是扫描整个表并创建一个新的临时表,表中每个组的所有行应为连续的,然后使用该临时表来找到组并应用累积函数(如果有)。在某些情况中,MySQL能够做得更好,即通过索引...
  • zljjava
  • zljjava
  • 2015年08月04日 17:04
  • 296

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

满足GROUP BY子句的最一般的方法是扫描整个表并创建一个新的临时表,表中每个组的所有行应为连续的,然后使用该临时表来找到组并应用累积函数(如果有)。在某些情况中,MySQL能够做得更好,即通过索引...

分析Oracle索引扫描四大类

 学习Oracle时,你可能会遇到Oracle索引扫描问题,这里将介绍Oracle索引扫描问题的解决方法,在这里拿出来和大家分享一下。根据索引的类型与where限制条件的不同,有4种类型的Oracle...
  • csc0211
  • csc0211
  • 2011年04月03日 22:46
  • 768
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:MySQL松散索引扫描与紧凑索引扫描
举报原因:
原因补充:

(最多只允许输入30个字)