【问题标题】:mysql index usage for query with ORmysql索引使用OR查询
【发布时间】:2016-05-09 21:48:19
【问题描述】:

我有一个这样的查询:

SELECT account.name, address.first_line 
FROM account
JOIN address ON address.id = account.address_id
WHERE
( account.date_updated >= '2016-05-05 12:00:00' 
OR
address.date_updated >= '2016-05-05 12:00:00' )

用户表和地址表在它们各自的“date_updated”列上都有一个索引,但是当我解释时,这些索引都没有被使用。

有什么办法可以改变吗?还是我只需要运行两个单独的查询来获取我想要的信息以及正在使用的索引。

我认为这与这个问题不同:MySQL: how to index an "OR" clause 因为“OR”两侧的字段来自不同的表,因此您不能在它们上放置复合索引。

【问题讨论】:

标签: mysql sql select indexing


【解决方案1】:

数据库很难优化OR。一种方法是使用UNIONUNION ALL

SELECT a.name, ad.first_line 
FROM account a JOIN
     address ad
     ON ad.id = a.address_id
WHERE a.date_updated >= '2016-05-05 12:00:00' 
UNION ALL
SELECT a.name, ad.first_line 
FROM account a JOIN
     address ad
     ON ad.id = a.address_id
WHERE ad.date_updated >= '2016-05-05 12:00:00' AND
      a.date_updated < '2016-05-05 12:00:00'

您可以使用UNION 而不是UNION ALL 编写此查询,并省略NOT EXISTS 子句。但是,UNION 中的重复消除通常比使用 WHERE 子句消除可能的重复要慢。

【讨论】:

    【解决方案2】:

    MySQL 不为其中包含 ORWHERE 子句使用索引。 This question 有更多信息。 MySQLWHERE clause documentation.

    我会尝试将两者结合在一起

    SELECT account.name, address.first_line FROM account 
    JOIN address ON address.id = account.address_id 
    WHERE account.date_updated >= '2016-05-05 12:00:00'
    
    UNION
    
    SELECT account.name, address.first_line FROM account 
    JOIN address ON address.id = account.address_id 
    WHERE address.date_updated >= '2016-05-05 12:00:00'
    

    【讨论】:

    • 戈登的回答比这个略好;他解释了原因。
    猜你喜欢
    • 2012-04-07
    • 1970-01-01
    • 2012-07-11
    • 1970-01-01
    • 2013-07-10
    • 2016-07-29
    • 1970-01-01
    • 2011-07-22
    相关资源
    最近更新 更多