0

我在一个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 秒)。另一个查询需要大约 6 秒,这很慢。我将不胜感激一些评论以加快速度:-)

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

  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
4

1 回答 1

3

尝试进行两次连接并将“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
于 2012-07-13T15:00:18.247 回答