为什么MySQL在使用DATE时会丢弃我的索引(`table` .column`)

时间:2014-08-07 08:27:33

标签: mysql sql indexing query-optimization innodb

我有一个带有几列的MySQL innodb表。 其中一个被命名为" dateCreated"这是DATETIME列,并且已编入索引。

我的查询:

        SELECT 
            *
        FROM 
            `table1`
        WHERE 
            DATE(`dateCreated`) BETWEEN '2014-8-7' AND '2013-8-7'

MySQL由于某种原因拒绝使用dateCreated列上的索引(即使使用USE INDEXFORCE INDEX

但是,如果我将查询更改为:

        SELECT 
            *
        FROM 
            `table1`
        WHERE 
           `dateCreated` BETWEEN '2014-8-7' AND '2013-8-7'

请注意 DATE(...) 删除

MySQL使用索引就好了。 我可以在不使用DATE()函数的情况下进行管理,但这对我来说很奇怪。

据我所知,也许MySQL索引完整的日期和时间,当只搜索其中的一部分时,它会变得混乱或者其他东西。但必须有一种方法可以使用部分日期(比方说MONTH(...)DATE(...))并仍然可以从索引列中受益,并避免全表扫描。

有什么想法..?

感谢。

1 个答案:

答案 0 :(得分:1)

正如您在将该函数应用于该字段时所观察到的那样,您将销毁对索引的访问权限。所以,

如果您不使用它们将会有所帮助。将函数应用于数据的基本原理是,您可以获取与参数匹配的数据。只有2个参数日期和几百个?千?百万?数据行。为什么不对此进行反转,更改参数以适应数据? (使其成为“sargable”谓词)

    SELECT 
        *
    FROM 
        `table1`
    WHERE 
         ( `dateCreated` >= '2013-08-07' AND `dateCreated` < '2014-08-07' )

    ;
  • 注意首先使用2013-08-07,如果在两者之间也使用,则必须如此。如果第一个日期比第二个日期更年轻,您将无法获得任何结果。
  • 另请注意,完全包含12个月的数据&gt; ='2013-08-07'AND&lt; '2014-08-07',我认为这就是你所寻求的。
  • 使用日期(dateCreated)和之间的组合将包括1天太多,因为将包括“2014-08-07”期间的所有事件。如果你故意想要一年零一天,那么在更高的日期加上1天,即它将是&lt; '2014-08-08'