我将在其中运行查询的表上的正确索引是什么
SELECT * FROM table WHERE NOW() BETWEEN date1_col AND date2_col
date1_col
上的索引是否足够,或者我必须为两列建立索引,或者需要复杂的索引?
此外,是否会为每一行计算NOW()
?在构造查询时将其作为文字提供会更好吗?
最佳答案
BETWEEN date_1 AND date_2
无法优化。但是,优化器将在运行时在这些之间进行选择:
INDEX(date_1, date_2) if the date is near the end of the date_1 values, or
INDEX(date_2, date_1) if the date is near the start of that index.
因此,拥有这两个索引。在最坏的情况下,查询将不得不扫描近一半的表。
那么,为什么不只使用 1 列版本呢?让我们进一步剖析一下......索引是根据指定列排序的 B+Tree。这样的树可以高效地进行线性扫描(从开始到日期或从日期到结束,取决于哪个索引),但之后需要检查 date_1/2 的另一个。
如果您只有 INDEX(date_1)
,那么它必须进入数据所在的 BTree 来获取 date_2
来检查它。
另一方面,如果您使用 INDEX(date_1, date_2)
,则该值就在那里,并且可以更快地测试“附加条件”。在非 JSON EXPLAIN
中,由 Extra 列中的“使用索引条件”指示。这是“ICP”。
我认为(但不确定)仅使用 2 列索引会更好。
注意:我认为 ICP 是在 5.6.10 中添加的。所以这取决于您的版本有多旧。
“覆盖”索引是指包含SELECT
中提到的所有 列的索引。这甚至更好,但它有一定的局限性,因为将 SELECT user
更改为 SELECT user, foo
使这些不再“覆盖”:
INDEX(date_1, date_2, user)
INDEX(date_2, date_1, user)
关于mysql - Between 子句的正确索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41699516/