应在此处索引哪些键以使此查询最佳

Posted

技术标签:

【中文标题】应在此处索引哪些键以使此查询最佳【英文标题】:What keys should be indexed here to make this query optimal 【发布时间】:2016-07-06 22:08:37 【问题描述】:

我的查询如下所示:

SELECT * from foo
  WHERE days >= DATEDIFF(CURDATE(), last_day)

在这种情况下,daysINTlast_dayDATE 列。

所以我需要在这里为dayslast_day 设置两个单独的索引?

【问题讨论】:

由于使用的是函数,因此last_day不能作为索引。天可以,但性能增益实际上取决于数据的差异。 【参考方案1】:

这个查询谓词days >= DATEDIFF(CURDATE(), last_day) 本质上不是sargeable。

如果您保留当前的表格设计,您可能会从(last_day, days) 上的复合索引中受益。然而,满足查询需要对该索引进行全面扫描。

这些列之一或两者上的单列索引对于提高此查询的性能将毫无用处或更差。

如果你必须让这个查询执行得非常好,你需要重新组织你的表。让我们弄清楚。看起来您正在尝试排除“过期”记录:您想要expiration_date < CURDATE()那是一个可搜索的搜索谓词。

所以如果你在表中添加了一个新列expiration_date,然后设置如下:

 UPDATE foo SET expiration_date = last_day + INTERVAL days DAY

然后将其编入索引,您将获得一个性能良好的查询。

【讨论】:

这非常有用。谢谢。【参考方案2】:

您必须小心索引,它们可以帮助您阅读,但它们会降低插入性能。

您可以考虑在 last_day 字段上创建一个分区。

我应该尝试只在 last_day 字段中创建,但是,我认为最好是使用不同的配置进行一些性能测试。

【讨论】:

我不担心这张桌子上的 INSERT 性能。它主要是读取查询。【参考方案3】:

由于您在 where 条件中使用表达式,mysql 将无法在两个字段中的任何一个上使用索引。如果你经常使用这个表达式并且你至少有mysql v5.7.8,那么你可以创建一个generated column并在上面创建一个索引。

另一个选项是创建一个常规列并将其值设置为此表达式的结果并索引该列。您将需要触发器来保持更新。

【讨论】:

以上是关于应在此处索引哪些键以使此查询最佳的主要内容,如果未能解决你的问题,请参考以下文章

MySQL - 查找查询的最佳索引

如何找到选择查询的最佳索引

Mysql 索引:查询生成器的最佳实践

postgres 上的这个延迟作业查询的最佳索引是啥?

唯一列的最佳索引类型,如果对数据进行物理排序,查询将更快

LIKE查询的最佳Postgres文本索引?