在MySQL中强制索引似乎不起作用

时间:2016-02-18 23:14:28

标签: mysql

我尝试创建一个SQL查询,在特定时间范围内获得服务的总出勤率。

我的查询工作正常,但出于某种原因,它在单个表上进行全表扫描而不使用索引(即使我使用FORCE INDEX时)。

这是my schema, query and output的实时样本。

运行查询后,您会看到st具有service_id的可能密钥,而是执行全表扫描(ALL)。

我一直在不同的表连接上使用FORCE INDEX,但似乎无法使所有连接的表使用正确的索引。更改一个索引会影响另一个索引我认为我要么设置错误的索引,要么完全错过了一些明显的东西。

有什么想法吗?

1 个答案:

答案 0 :(得分:3)

一个想法。我不认为你的查询正在做你认为它正在做的事情。

在我看来,你已经有了不应该有的parens。 这里:

  WHERE st.time BETWEEN('2016-01-01' AND '2016-01-03') AND
        st.deleted = 0

我认为MySQL正在评估其中的内容......

    ('2016-01-01' AND '2016-01-03')

并且计算结果为TRUE,返回为整数值1。所以你拥有的东西实际上相当于:

  WHERE st.time BETWEEN 1 AND st.deleted = 0

有一个优先顺序......要么首先评估相等比较,要么AND(被认为是BETWEEN比较的一部分)。它将等同于:

  WHERE ( st.time BETWEEN 1 AND st.deleted ) = 0

-OR -

  WHERE st.time BETWEEN 1 AND ( st.deleted = 0 )

我需要运行一些测试来弄清楚它在做什么。但在任何一种情况下,它不可能是你期望的,或者你真正想要的。 MySQL无法使用带有time前导列的索引进行范围扫描,因为在此之前它需要deleted列的值。

我建议您在开始使用索引之前先修复查询。

我在想你想要的是这样的:

  WHERE st.time BETWEEN '2016-01-01' AND '2016-01-03'
    AND st.deleted = 0

为了比较,请考虑这些陈述的回报:

SELECT '2016-01-02' BETWEEN ('2016-01-01' AND '2016-01-03') AND 1=1  --> 0

SELECT '2016-01-02' BETWEEN  '2016-01-01' AND '2016-01-03'  AND 1=1  --> 1

SELECT '2016-01-02' BETWEEN ('2016-01-01' AND '2016-01-03')  --> syntax error