【问题标题】:mysql join performance IF multiple OR conditionsmysql join性能IF多个OR条件
【发布时间】:2012-07-13 09:46:31
【问题描述】:

我在一个 mysql table1 中保存一组节点,在另一个(table2)中保存一个边表。节点带有主键,边使用这个“外键”

**table1**
id label
1  node1
2  node2
3  node3

**table2**
FK_first FK_sec   rel
1        3        guardian
2        1        guardian
1        3        times

我知道 db-design 并不完美,但它很简单...... 现在我想要每个节点的“rel”数量并执行如下查询:

SELECT 
  label, 
  COUNT( rel ) as freq
FROM
  `table1` 
  LEFT JOIN table2 ON (id=FK_first OR id=FK_second) 
GROUP BY label
ORDER BY freq DESC

我有大约 1000 个节点和 2000 条边。使用 ON (id=FK_first OR id=FK_second) 的查询,则查询速度更快(

  1. LEFT JOIN table2 ON (id=FK_first OR id=FK_second) ~6 sec
  2. LEFT JOIN table2 ON (id=FK_first) ~0.16 秒
  3. LEFT JOIN table2 ON (id=FK_second) ~0.16 秒

  4. LEFT JOIN table2 ON id IN (FK_first,FK_second) ~6 sec

解释1: id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE table1 ALL NULL NULL NULL NULL 2571 使用临时;使用文件排序 1 简单表 2 ALL FK_first,FK_second,FK_first_2 NULL NULL NULL 3858 解释2: id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE table1 index NULL PRIMARY 2 NULL 2571 使用索引;使用临时的;使用文件排序 1 简单表 2 参考 FK_first,FK_first_2 FK_first_2 4 table1.id 1

【问题讨论】:

  • 你有FK_second的索引吗?
  • @Michael:考虑到最后一段还不是很清楚,我们应该问他是否对查询中使用的键没有or的索引。
  • 我一直和你在一起,直到实际的问题......你能显示 2 个查询吗?描述你的索引?
  • 是的,我有一个 FK_First 索引和另一个 FK_second 索引以及两者的组合...
  • 为了更清楚:LEFT JOIN table2 ON (id=FK_first OR id=FK_second) ~6 sec LEFT JOIN table2 ON (id=FK_first) ~0.16 sec LEFT JOIN table2 ON (id=FK_second ) ~0.16 秒

标签: mysql performance networking join


【解决方案1】:

尝试进行两次连接并将“OR”移动到 COUNT() 函数中:

对于每一行,这会在 FK1 上连接 table2 一次,然后在 FK2 上再次连接(如果它尚未通过 FK1 连接到该行。然后在 COUNT 中,我们指定仅具有连接的 rel 列的行作为非空。

SELECT 
  label, 
  COUNT( table2A.rel || table2B.rel ) as freq
FROM
  `table1` 
  LEFT JOIN 
    table2 as table2A 
    ON id=table2A.FK_first
  LEFT JOIN 
    table2 as table2B 
    ON id=table2B.FK_second 
    AND  table2A.FKFirst != table2B.FKFirst
GROUP BY label
ORDER BY freq DESC

【讨论】:

  • 这可以将其加速到大约 2 秒,但在我看来它非常复杂且不够快...
  • 看看这个解决方案的解释。我认为这是正确的做法。剩余的缓慢可能是由于 GROUP/ORDER 所需的文件排序。因此(1)尝试索引“标签”,因为您正在对其进行分组。 (2) 尝试增加@@max_heap_table_size 和@@tmp_table_size,尤其是在执行过程中看到“converting HEAP to MyISAM”或“copying to tmp table on disk”的线程状态。 (不过,我认为您的结果集不足以触发此操作。)
  • 是的,你是对的!在我使用 id 而不是标签进行分组之后,它非常快。感谢大家帮助寻找解决方案!
  • 如果基于此逻辑,请随时编辑我的答案以反映您最终使用的最终解决方案,以便将来发现此问题的任何人都能清楚地看到最终解决方案是什么:- )
  • 嘿,如果有人处于相同的情况但使用INNER join 而不是left join,那么在这种情况下拆分为 2 个连接将不起作用,对吧?
猜你喜欢
  • 2023-03-12
  • 2017-01-27
  • 2017-03-18
  • 1970-01-01
  • 2013-05-14
  • 2011-02-15
  • 1970-01-01
  • 2017-04-07
  • 2017-07-29
相关资源
最近更新 更多