【问题标题】:How to index a table with ranges?如何索引具有范围的表?
【发布时间】:2016-08-17 12:00:41
【问题描述】:

我有一个包含以下字段的表:idsexage_minage_maxurl

该表格将按性别、年龄范围和 ID 进行过滤。一个常见的查询是:

SELECT `url` FROM foo WHERE (`id` NOT BETWEEN %lim_1% AND %lim_2%) 
AND `sex`=%sex% 
AND `age_min` <= %age% AND `age_max` >= %age%

我的问题是:我应该设置哪些索引以优化查询响应时间?另外,如果查询本身可以以某种方式优化,我也想知道。

【问题讨论】:

  • 我觉得应该是id
  • @HamzaZafeer 只是id?我正在考虑为除url 之外的所有字段添加索引,但我不知道MySQL 将如何管理它。也许还有一些关于年龄范围的事情。
  • IMO 这可能最好放在 DBA.stackexchange.com 上,因为它是关于设计考虑,而不是专门编程。

标签: mysql indexing query-performance


【解决方案1】:

这种查询很难用索引来加速; age_min &lt;= %age% AND age_max &gt;= %age% 过滤不能被查询计划者或程序员重构为简洁的小索引范围扫描。

因此,您应该创建一个覆盖索引并希望获得最好的结果。

您在sex = %sex% 上有一个相等过滤器,因此该列应引导索引。

age_minage_max 上有半扫描范围过滤器。如果您知道其中一个比另一个更具选择性,请选择它作为索引中的下一列。否则,只需选择两者之一。

然后,将表的其余列包含在索引中。所以你会得到

 (sex, age_min, age_max, id, url)

在索引中。查询计划器可以只扫描该索引的一部分,然后从索引中满足查询。如果您查找覆盖索引,您可以了解有关此技术的更多信息。

注意。如果您没有在过滤器中包含 sex = %sex% 子句,则该索引对于满足该查询将变得毫无价值。

注意。 MySQL 几乎永远不会使用多个索引来满足单个 WHERE 子句。因此,将单列索引放在大量列上几乎不是一个好主意。

注意。如果表包含少于几百行,索引它不会有什么坏处,但可能不会有太大帮助。

【讨论】:

  • @2nd note - “几乎”? MySQL 何时为单个 WHERE 子句使用多个索引?
  • “从不”是一个极端的说法,尤其是对于一个正在积极开发的开源系统。因此“几乎从来没有”。
  • 我会说“索引合并”的使用不到千分之一。 EXPLAIN SELECT ... 清楚地显示它何时使用它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-29
  • 1970-01-01
  • 1970-01-01
  • 2010-10-08
  • 2010-11-25
  • 2021-01-19
相关资源
最近更新 更多