我有一个包含近10亿条记录的MyISAM表,其中有三个字段: a、b和c。
该表在列a、b和c上按该顺序具有btree多字段索引。分析索引显示,该索引中字段的基数为:
a: 112 (整型)
b: 2694 (整型)
c: 936426795 (日期时间)
这意味着对于a,大约有100个不同的值,对于b,大约有20个不同的值,对于a和b的每个组合,都有大量的c的值。
我想在a的特定值上执行查询,在c上执行范围查询。
select a, b, c from mytable where a=4 and c >= "2011-01-01 00:00:00" and c < "2011-01-02 00:00:00"得到解释后的查询表明它确实会使用索引,但我不知道它是否只使用索引的第一个字段,然后扫描表的其余部分,或者它是否足够聪明,为b的每个值应用第三个字段索引,这与执行20个不同的查询相同,每个不同的b值一个查询。
知道mysql索引内部工作原理的人能回答这个问题吗?
编辑:我不是问我是否可以让mysql只在a和c上使用索引。我知道btree是如何工作的,我知道你只能在a,a和b,或者a和b和c上使用它。我想知道mysql优化器是否足够聪明,将索引应用于b中的所有值,这样它就可以使用a+b+c索引,因为b的基数非常小。
考虑一个更简单的例子。一个有两列的表:a和b,索引的基数是1比a,10000000比b。Mysql应该足够聪明,知道只有一个a的值,因此这个索引等同于一个只有b的索引,当只在b上执行查询时,应该使用这个索引。
发布于 2011-08-09 10:54:40
MySQL Reference Manual :: How MySQL Uses Indexes
如果表具有多列索引,则优化器可以使用索引最左侧的任何前缀来查找行。例如,如果您在(col1,col2,col3)上有一个三列索引,那么在(col1)、(col1,col2)和(col1,col2,col3)上就有索引搜索功能。如果列不构成索引的最左侧前缀,则MySQL不能使用索引。
a,c不是索引a,b,c的最左边的前缀,因此索引不能用于解析对c的搜索。
发布于 2012-05-25 14:48:53
从一些数据库引擎足够智能地扫描索引而不是扫描表的角度来看,这个问题是有意义的。(正是由于这个原因,它们允许将“数据”存储在索引中。)扫描索引比将索引连接到基本数据,然后根据where子句限制(排除)返回的行要快。
只连接索引中满足where条件的行(在索引中的列上)是有意义的。尤其是如果你正在运行一个大的密钥缓存...
这似乎不会发生在MySQL中,这是令人失望的。因此,不是。
发布于 2014-02-19 19:39:16
下面是一些与mysql使用B-TREE索引相关的事实和一个理解这一逻辑的示例。
a)如果有任何表具有约75%相同的数据,那么索引将不会被使用,取而代之的是mysql将进行表扫描。
b)通常情况下,mysql对每个表只使用一个索引。
c)索引排序方法: Mysql将按照它们的顺序使用索引。
例如,在a,b和c字段idx_a_b_c(a,b,c)上有一个组合索引
i.从mytable中选择a、b、c,其中a=4
此查询将使用索引,因为'a‘列是索引顺序中的第一列。
二、从mytable中选择a、b、c,其中a=4和b=5
该查询将在a&b上使用组合索引,因为这些列是按索引顺序连续。
三、从mytable中选择a,b,c,其中a=4和b=5,c >= "2011-01-01 00:00:00“
该查询将在a、b和c上使用组合索引,因为这些列是按索引顺序连续。
四.从mytable中选择a,b,c,其中c >= "2011-01-01 00:00:00“
此查询将不使用索引,因为mysql从最左角考虑索引,并且列c不是索引中最左侧的列。
v.从mytable中选择a,b,c,其中a=4和c >= "2011-01-01 00:00:00“和c< "2011-01-02 00:00:00”
此查询将仅使用'a‘列的索引,而不使用'c’列的索引,因为此处的连续性从左侧开始中断。因此,此查询将在列上使用索引,然后根据列a上的筛选器,在表中扫描列c中的相应行。
https://stackoverflow.com/questions/6990895
复制相似问题