2012-07-13 47 views
0

我在一个mysql table1中保存一组节点,在另一个mysql1中保存一组边(table2)。节点配备了主键和边缘使用“外键”mysql加入性能如果有多个OR条件

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

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

我知道数据库的设计并不完美,但它的简单... 现在我想“版本”的数量为每个节点和做一个查询如:

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 或id = FK_second ),则查询速度更快(< 1秒)。另一个查询需要大约6秒,这是慢的。 我将不胜感激一些评论加快这一点:-)

  1. LEFT JOIN表2 ON(ID = FK_first或ID = FK_second)〜6秒
  2. LEFT JOIN表2 ON(ID = FK_first)〜 0.16秒
  3. LEFT JOIN表2 ON(ID = FK_second)〜0.16秒

  4. LEFT JOIN表2的ID IN(FK_first,FK_second)〜6秒

 

EXPLAIN 1: 
     id select_type table type possible_keys     key key_len ref rows Extra 
     1 SIMPLE   table1 ALL NULL       NULL NULL NULL 2571 Using temporary; Using filesort 
     1 SIMPLE   table2 ALL FK_first,FK_second,FK_first_2 NULL NULL NULL 3858  

EXPLAIN 2: 
id select_type table type possible_keys  key key_len ref  rows Extra 
1 SIMPLE  table1 index NULL    PRIMARY 2 NULL  2571 Using index; Using temporary; Using filesort 
1 SIMPLE  table2 ref FK_first,FK_first_2 FK_first_2 4 table1.id 1 
+0

您是否有'FK_second'上的索引? – 2012-07-13 14:16:11

+0

@Michael:考虑到最后一段很不明确,我们应该询问他是否有没有or的查询中使用的密钥索引。 – Razvan 2012-07-13 14:18:27

+0

我和你在一起,直到真正的问题...你可以显示2个查询?描述你的索引? – Randy 2012-07-13 14:20:39

回答

3

尽量做两件连接和移动“或”入COUNT()函数:在FK2上FK1一次

的每一行,该联接表2,然后再(如果它尚未加入到通过FK1行。然后在COUNT中,我们指定只有连接的rel列为非null的行。

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 
+0

这加速了~2秒,但它非常复杂,而不是在我看来足够快... – user1523756 2012-07-13 15:11:05

+0

看看这个解决方案的解释。我认为这是正确的做法。其余的缓慢可能是由于GROUP/ORDER所需的文件夹。所以(1)尝试索引'标签',因为你正在对它进行分组。 (2)尝试增加@@ max_heap_table_size和@@ tmp_table_size,特别是在执行期间看到线程状态为“将HEAP转换为MyISAM”或“将数据复制到磁盘上的tmp表”时。 (不过,我认为你的结果集可能足以触发这个问题。) – 2012-07-13 16:24:53

+0

是的,你是对的!在我使用id并且没有标签来分组之后,它非常快速。谢谢大家帮忙找到解决方案! – user1523756 2012-07-13 16:38:45