使用2个范围的查询的索引设计

时间:2012-08-11 21:46:09

标签: mysql sql indexing

当我的查询使用2个字段的范围时,我试图找出如何为我的数据设计索引。

expenses_tbl:
idx        date     category      amount
auto-inc   INT       TINYINT      DECIMAL(7,2)
PK

列类别定义费用类型。比如娱乐,服装,教育等。其他栏目很明显。

我对此表的一个疑问是查找所有那些在给定日期范围内费用超过50美元的情况。此查询将如下所示:

SELECT date, category, amount 
FROM expenses_tbl
WHERE date > 120101 AND date < 120811 
      AND amount > 50.00;

如何针对此特定查询在此表上设计索引/二级索引。

假设:表格非常大(目前不是,但这给了我一个学习的空间)。

3 个答案:

答案 0 :(得分:3)

MySQL通常不支持复合索引的多个部分的范围。它将使用日期的索引或金额的索引,但不能同时使用两者。如果你有两个索引,它可能会做一个索引合并,每个索引一个,但我不确定。

我在添加这些索引之前和之后检查EXPLAIN

CREATE INDEX date_idx ON expenses_tbl (date);
CREATE INDEX amount_idx ON expenses_tbl (amount);

复合索引范围 - http://dev.mysql.com/doc/refman/5.5/en/range-access-multi-part.html

索引合并 - http://dev.mysql.com/doc/refman/5.0/en/index-merge-optimization.html

答案 1 :(得分:1)

还有一些尚未提及的要点:

索引中列的顺序可以有所不同。您可能想要尝试这两个索引:

(date, amount)
(amount, date)

选哪个?通常,您希望最多选择性条件成为索引中的第一列。

  • 如果您的日期范围很大,但很少有费用超过50美元,那么您希望首先在索引中使用amount
  • 如果您的日期范围较窄且大部分费用超过50美元,那么您应该先date
  • 如果两个索引都存在,那么MySQL将选择估算成本最低的索引。

您可以尝试添加两个索引,然后查看EXPLAIN SELECT ...的输出,以查看MySQL为您的查询选择的索引。


您可能还想考虑覆盖索引。通过在索引中包含列category(作为最后一列),这意味着您的查询所需的所有数据都可以在索引中使用,因此MySQL根本不需要查看基表来获取查询结果。

答案 2 :(得分:0)

您的问题的一般答案是您需要一个带有两个键的复合索引。第一个是日期,第二个是金额。

请注意,此索引适用于对日期或日期以及费用有限制的查询。它仅适用于仅限于费用的查询。如果您同时拥有这两种类型,则可能需要花费第二个索引。

如果表真的非常大,那么您可能希望按日期对其进行分区,并在每个分区内按费用构建索引。