【问题标题】:MySQL multiple OR's in WHEREMySQL 多个 OR 在 WHERE
【发布时间】:2017-10-09 23:10:05
【问题描述】:

我有以下疑问:

SELECT
    b.business_name,
    b.address,
    b.city,
    b.state,
    b.phone_number,
    i.date
FROM business_table b
LEFT JOIN inspection_table i ON b.id = i.business_id
WHERE i.date = (
    SELECT MAX(i.date)
    FROM inspection_table i
    WHERE b.id = i.business_id
)
AND b.city LIKE '%Boston%'
OR b.city LIKE '%Dallas%'
OR b.city LIKE '%Seattle%'
OR b.city LIKE '%New York%'
OR b.city LIKE '%Portland%'
OR b.city LIKE '%San Antonio%'
OR b.city LIKE '%Los Angeles%'
OR b.city LIKE '%Miami%'
ORDER BY i.date DESC;

我得到了我想要的结果,但查询速度很慢(~17 秒)。有没有更好的方法来构造这个查询? city 字段在 business_table 中建立索引。

【问题讨论】:

  • 可以使用REGEXP (b.city REGEXP 'Boston|Dallas|Seattle'),但这实际上可能会稍微慢一些。不过,它不应该花费 17 秒。你的表有多少行?
  • ~32,000 行在我的表中
  • 您是否尝试在 OR 列表周围加上括号?还是您想要“来自波士顿的最新......以及来自其他城市的一切”?

标签: mysql full-text-search query-optimization


【解决方案1】:

常规索引根本无法帮助LIKE '%pattern' 查询。未使用索引,您的查询必须对表进行完整的表扫描。

如果您希望它使用 MySQL 进行高效搜索,则需要使用 Full-Text Search Functions

您可能会喜欢我的演示文稿Full Text Search Throwdown,其中我比较了 MySQL 的不同文本搜索方法。

【讨论】:

    【解决方案2】:

    我感觉你的 OR 是错误的,所以这是我认为更好的查询。

    SELECT
        b.business_name,
        b.address,
        b.city,
        b.state,
        b.phone_number,
        li.lastInspection AS `date`
    FROM (SELECT business_id, MAX(i.date) as lastInspection
          FROM inspection_table
          GROUP BY business_id) AS li
    INNER JOIN business_table b
    ON li.business_id = b.business_id
    WHERE b.city LIKE '%Boston%'
       OR b.city LIKE '%Dallas%'
       OR b.city LIKE '%Seattle%'
       OR b.city LIKE '%New York%'
       OR b.city LIKE '%Portland%'
       OR b.city LIKE '%San Antonio%'
       OR b.city LIKE '%Los Angeles%'
       OR b.city LIKE '%Miami%'
    ORDER BY li.lastInspection DESC
    ;
    

    如果您有大量城市或企业,这可能会很慢;但我敢打赌inspection_table (business_id, date) 的索引会加快速度。

    理想情况下,这将获得您的最后一次检查,找到他们的业务,然后过滤业务;如果不是,您可以通过将除 WHERE 条件之外的所有条件放在子查询中来强制它,并让外部查询进行最终过滤。

    【讨论】:

      【解决方案3】:

      查询的表述似乎存在多个问题。其他答案带来了一些修复。我会努力解决所有问题。

      括号是必须的——x AND y OR z OR w 被视为(x AND y) OR z OR w。这可能会修复意图和性能。

      您正在寻找South BostonBoston?还有Boston Heights?如果不是,则去掉通配符 (%)。这样就可以索引city

      如果您确实需要通配符,那么使用FULLTEXT 索引和MATCH...AGAINST... 会运行得更快。

      我认为,使用领先的%,REGEXP 建议黑曜石时代会更快,因为它只会扫描一次city

      如果business_id 不是PRIMARY KEY,添加这些:

      INDEX(business_id, date)
      INDEX(business_id, city)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-06-05
        • 1970-01-01
        • 2020-09-26
        • 1970-01-01
        • 1970-01-01
        • 2014-02-06
        • 1970-01-01
        相关资源
        最近更新 更多