>我有一个如下所示的查询:
SELECT * from foo
WHERE days >= DATEDIFF(CURDATE(), last_day)
在这种情况下,days
是一个 INT
. last_day
是DATE
列。
所以我在这里需要两个单独的索引来days
和last_day
?
此查询谓词 days >= DATEDIFF(CURDATE(), last_day)
本质上是不可优化的。
如果您保留当前的表设计,您可能会从 (last_day, days)
上的复合索引中受益。但是,满足查询将需要对该索引进行完全扫描。
其中一列或两列上的单列索引对于提高此查询的性能将毫无用处或更糟。
如果必须使此查询执行良好,则需要稍微重新组织表。让我们弄清楚。 看起来您正在尝试排除"过期"记录:您想要expiration_date < CURDATE()
.这是一个可优化的搜索谓词。
因此,如果您向表中添加了新列expiration_date
,然后按如下方式进行设置:
UPDATE foo SET expiration_date = last_day + INTERVAL days DAY
然后索引它,您将拥有一个性能良好的查询。
您必须小心索引,它们可以帮助您阅读,但它们会降低插入的性能。
您可以考虑在last_day字段上创建一个分区。
我应该尝试只在last_day领域创建,但是,我认为最好的方法是使用不同的配置进行一些性能测试。
由于您在 where 条件中使用表达式,mysql 将无法在这两个字段中的任何字段上使用索引。如果您经常使用此表达式并且至少具有 mysql v5.7.8,则可以创建一个生成的列并在其上创建索引。
另一种选择是创建一个常规列,并将其值设置为此表达式的结果,并为此列编制索引。您将需要触发器来保持其更新。