我有一张MyISAM表,有近10亿条记录,比方说有三个字段:a,b和c。
该表在列a,b和c上按顺序具有btree多字段索引。分析索引显示该索引中字段的基数为:
a:112(int)
b:2694(int)
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。 Mysql应该足够聪明,知道a只有一个值,因此这个索引只相当于b上的索引,并且只在b上执行查询时应该使用这个索引。
答案 0 :(得分:1)
MySQL Reference Manual :: How MySQL Uses Indexes
如果表有多列索引,则表示最左边的前缀 优化器可以使用index来查找行。例如,如果你 在(col1,col2,col3)上有一个三列索引,你已编入索引 搜索(col1),(col1,col2)和(col1,col2,col3)的功能。 如果列不形成索引的最左前缀,则MySQL不能使用索引。
a,c不是索引a,b,c的最左前缀,因此索引不能用于解析c上的搜索。
答案 1 :(得分:0)
从一些数据库引擎足够智能扫描索引而不是扫描表的角度来看,这个问题是有道理的。 (并且它们允许&#34;数据&#34;由于这个确切的原因存储在索引中。)扫描索引将比将索引加入基础数据更快,然后根据where限制(排除)返回的行子句。
只有索引中满足where条件的行(在索引中的列上)才会连接起来才有意义。特别是如果您正在运行大型密钥缓存...
看起来这在MySQL中并不会令人失望。 因此没有。
答案 2 :(得分:0)
以下是与mysql使用B-TREE索引相关的一些事实,以及一个了解此逻辑的示例。
a)如果任何表有约。 75%相同的数据然后索引不会被使用而不是mysql将进行表扫描。
b)通常,mysql每个表只使用一个索引。
c)索引排序方法:Mysql将根据订单使用索引。
例如,a,b和c字段的组合索引为idx_a_b_c(a,b,c)
我。从mytable中选择a,b,c,其中a = 4
此查询将使用索引,因为“a”列在索引顺序中排在第一位。
II。从mytable中选择a,b,c,其中a = 4且b = 5
此查询将在&amp;上使用组合索引。 b因为这些列按索引顺序继续。
III。从mytable中选择a,b,c,其中a = 4且b = 5且c&gt; =“2011-01-01 00:00:00”
此查询将在a,b&amp;上使用组合索引。 c,因为这些列按索引顺序继续。
IV。从mytable中选择a,b,c,其中c> =“2011-01-01 00:00:00”
此查询不会使用索引,因为mysql从最左角开始考虑索引,而c列不是索引中最左边的列。
诉从mytable中选择a,b,c,其中a = 4且c&gt; =“2011-01-01 00:00:00”并且c&lt; “2011-01-02 00:00:00”
此查询将仅使用“a”列上的索引而不使用“c”列中的索引,因为此处的连续性从左侧开始。因此,此查询将使用列上的索引,然后根据列a上的过滤器扫描表格中的列c以查找相应的行。