【问题标题】:Query speed drops on two "=" comparisons in WHERE clauseWHERE 子句中两个“=”比较的查询速度下降
【发布时间】:2018-03-24 06:23:52
【问题描述】:

我有一个音乐数据库,其中包含一个用于发布和发布标题的表格。此“releases_view”获取曲目的标题/title_id 和替代标题/替代 title_id。这是视图的代码:

SELECT
    t1.`title` AS title,
    t1.`id` AS title_id,
    t2.`title` AS title_alt,
    t2.`id` AS title_alt_id

FROM
    releases

LEFT JOIN titles t1 ON t1.`id`=`releases`.`title_id`
LEFT JOIN titles t2 ON t2.`id`=`releases`.`title_alt_id`

联接表中的title_idtitle_alt_id 字段都是int(11)titletitle_alt 都是varchars。

问题

此查询将花费不到 1 毫秒:

SELECT * FROM `releases_view` WHERE title_id=12345

此查询也将花费不到 1 毫秒:

SELECT * FROM `releases_view` WHERE title_id=12345 OR title_alt_id!=54321

但是:这个查询需要 0.2 秒。 慢了 200 倍!

SELECT * FROM `releases_view` WHERE title_id=20956 OR title_alt_id=38849

一旦我在 WHERE 子句中使用“=”进行了两次比较,事情就会变得很慢(尽管所有查询都只有几个结果)。

你能帮我理解发生了什么吗?

编辑

'EXPLAIN' 显示 title_alt_id 的 USING WHERE,但我不明白为什么。我怎样才能避免这种情况?

** 编辑 ** 这是解释转储。

id  select_type     table       partitions  type    possible_keys   key     key_len ref                         rows    Extra 
1   SIMPLE          releases    NULL        ALL     NULL            NULL    NULL    NULL                        76802   Using temporary; Using filesort
1   SIMPLE          t1          NULL        eq_ref  PRIMARY         PRIMARY 4       db.releases.title_id        1    
1   SIMPLE          t2          NULL        eq_ref  PRIMARY         PRIMARY 4       db.releases.title_alt_id    1       Using where

【问题讨论】:

  • 速度并没有因为两次比较而降低,而是因为ORJOINs而降低。
  • @axiac,查询 OP 指向的位置没有 JOIN
  • @axiac:但是示例二也使用了 JOIN 并且它有 OR。您的声明似乎无效。
  • @Rahul。来自VIEW 的查询SELECTs 和视图的定义使用了两个LEFT JOINs。该视图只是 MySQL 上的别名。定义视图不会运行用于定义它的查询。该查询被合并到SELECTs 来自VIEW 的查询中。检查EXPLAIN的输出。
  • @ArminHierstetter 我没有任何要求。我向您提供了为什么最后一个查询很慢的提示。 = OR == OR != 不同。

标签: mysql performance join


【解决方案1】:

“真的很慢”是因为优化器不能很好地与OR 配合使用。

(优化器的)计划 A:扫描整个表,评估整个 OR

计划 B:“索引合并联合”可用于 title_id = 20956 OR title_alt_id = 38849 如果您在 title_idtitle_alt_id 中有单独的索引:使用每个索引获取两个 PRIMARY KEYs 列表并“合并”列表,然后进入表格以获取*。多步骤,不便宜。所以 B 计划很少使用。

title_id = 12345 OR title_alt_id != 54321 是个谜,因为它应该返回大部分表格。请提供EXPLAIN SELECT...

LEFT JOIN(相对于JOIN)需要假设“右”表中可能缺少该行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-09
    • 1970-01-01
    • 1970-01-01
    • 2022-12-10
    • 2015-08-10
    • 2012-08-06
    • 1970-01-01
    相关资源
    最近更新 更多