1

假设我有一张桌子events {id, userid, create_time, country, type, page, browser}

我对所有列都有索引。如果我做一个查询

select count(*) from events where id > ? and id < ? and userid>? and userid<? and create_time>? and create_time<? and browser=? and country=? and page=?

我有以下问题:

  1. 我的所有索引都会被使用吗?如果没有,如何实现。
  2. 多列索引会更好吗?
  3. 如果我在 (id,userid,page) 上有一个多列索引,它会被使用吗?如果是这样,是否还会使用其他索引?
  4. 如果我有一个包含所有列的多列索引,但我的查询不包括所有列,那么是否会使用该索引?
4

2 回答 2

1

我的所有索引都会被使用吗?

不会。只会使用一个索引。您可以在 EXPLAIN 的输出中看到这一点。

多列索引会更好吗?

如果你有平等约束,是的。但在您的查询中似乎并非如此。拥有一个覆盖索引也很好——这是一个包含查询所需的所有值的索引。

如果我在 (id,userid,page) 上有一个多列索引,它会被使用吗?

可能,但我建议添加create_time,因为这会使它成为一个覆盖索引。您不需要page在索引中,因为它没有在您的查询中使用。

如果我有一个包含所有列的多列索引,但我的查询不包括所有列,那么是否会使用该索引?

这取决于列的顺序。如果查询想要使用索引,create_time那么它可以使用索引(create_time, country)。但是索引(country, create_time)无济于事。

于 2012-06-28T22:59:31.030 回答
0

问:我的所有索引都会被使用吗?

答:极不可能。MySQL 更有可能选择一个单一的索引,一个具有最高选择性(消除最多行)的索引,然后从索引引用中访问数据页。

MySQL 可能会执行索引合并操作,但这将是罕见的例外。你真的需要做一个EXPLAIN看看这是否正在发生,并做一些工作来开发一个 MySQL 将其视为最佳计划的案例。(可能有人已经完成了这项工作,并且有这样的测试用例。)

问:如果没有,如何实现。

A:你不想达到那个目的。您希望 MySQL 做的是生成一个最佳计划。索引合并计划很可能不是您查询的最佳计划。这样的操作需要 MySQL 将所有这些索引“匹配”在一起,这是一项繁重的工作。

问:多列索引会更好吗?

答:是的。您的特定查询的最佳索引是覆盖索引,它包括查询中引用的所有列。通常,您首先需要具有最高选择性和最高基数的列。您的查询似乎在进行范围扫描而不是相等性测试,您希望与列的整个值集相比,谓词中值范围最窄的列,首先在索引中。

问:如果我在 (id,userid,page) 上有一个多列索引,它会被使用吗?

答:可能。您在该索引的两个前导列上有范围扫描谓词,因此它绝对看起来像一个候选者。如果这些是您的查询中引用的唯一列,那么它更有可能使用索引。

您的查询文本中似乎对 create_time 的引用格式错误。看起来您打算在该列上有某种谓词。如果是这种情况,那么索引(id, userid, create_time)将是更好的候选者,因为这样可以从索引中满足查询,而无需引用数据页。

另一方面,对数据页进行全面扫描可能是更理想的计划。

问:如果是这样,是否还会使用其他索引?

答:极不可能。MySQL 将在表上使用“多个”索引的想法是关于 MySQL 如何使用索引的常见误解。这不是不可能的,但 INDEX MERGE 操作不太可能是最佳计划。

问:如果我有一个包含所有列的多列索引,但我的查询不包含所有列,那么是否会使用该索引?

答:有可能。如果 MySQL 确定使用该索引是最佳计划,则将使用它。更有可能使用的索引(如果可用)是一个覆盖索引,它只包含查询中引用的列。

于 2012-06-28T23:54:42.573 回答