【问题标题】:Index design for queries using 2 ranges使用 2 个范围的查询的索引设计
【发布时间】:2014-01-23 22:34:39
【问题描述】:

当我的查询使用 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;

我如何为此特定查询设计此表的索引/二级索引。

假设:表格非常大(目前还没有,但这给了我学习的空间)。

【问题讨论】:

  • @MarkByers:现在更新了问题。

标签: mysql sql indexing


【解决方案1】:

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

【讨论】:

  • 感谢您的注释和链接。我会检查他们。
  • @JoshuaMartell 。 . .感谢您的链接。我没有意识到mysql不使用范围内第二个键的索引。
  • 如果第一个键是常量,它会。如果你做了date IN (date1,date2,date3,date4) AND amount BETWEEN x AND y,我想它会同时使用。
  • @JoshuaMartell:我尝试了上述索引,但 mysql 没有为我的查询执行索引合并。我发现如果我还在索引中包含“类别”,那么复合索引对我的查询是有益的,因为它可以作为覆盖索引。从您在上面提供的复合索引链接中,它表明对于 BTREE 索引,一旦 mysql 找到一个键的范围请求,它就会停止使用复合索引中的后续键(这也是您和 Gordon 在上面的评论中提到的)。
【解决方案2】:

还有几点还没有提到:

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

(date, amount)
(amount, date)

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

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

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


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

【讨论】:

  • 我一直在想我需要多个覆盖索引。对于像“SELECT date, category, amount FROM costs_tbl WHERE date > 120101 AND category == 1”这样的查询,我需要覆盖索引(类别、日期、金额)。现在,对于我的问题中提到的查询,我可能需要启用索引合并。只是一个想法。
  • @Ethan:在某些情况下,以不同的顺序在同一列上添加多个索引是有意义的。但是请记住,索引是有代价的——您添加的每个索引都意味着对表的修改将花费更长的时间。对于每个索引,您应该考虑读取的好处与写入的成本。
【解决方案3】:

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

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

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

【讨论】:

  • 同意。现在,对于对日期和费用都有限制的查询,除了复合索引(日期、金额)之外,我还能做些什么更好的事情?
  • @Ethan 。 . .您的问题的答案是按日期对数据进行分区并建立费用索引。费用索引应按日期划分。
  • 澄清一下:您是说基于日期的表上的第一个分区,然后在分区表上基于日期的费用索引上的另一个分区?
  • 没有。范围分区方案通常只在一列上。它根据日期范围将表格物理拆分为多个文件。然后,您可以建立费用索引。分区和索引是两个不同的东西,但它们以您想要的方式交互。
  • 对。因此,即使我的表很大,为我的查询处理的数据也更少。谢谢。
猜你喜欢
  • 1970-01-01
  • 2018-05-24
  • 1970-01-01
  • 1970-01-01
  • 2018-03-27
  • 1970-01-01
  • 2021-05-18
  • 2013-01-02
  • 1970-01-01
相关资源
最近更新 更多