0

1つのmysqltable1にノードのセットを保持し、別の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秒
  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秒

説明1:
        idselect_typeテーブルタイプpossible_keyskeykey_len ref rows Extra
        1 SIMPLE table1 ALL NULL NULL NULLNULL2571一時的なものを使用します。filesortの使用
        1 SIMPLE table2 ALL FK_first、FK_second、FK_first_2 NULL NULL NULL 3858    

説明2:
idselect_typeテーブルタイプpossible_keyskeykey_len ref rows Extra
1 SIMPLE table1 index NULL PRIMARY 2NULL2571インデックスを使用します。一時的な使用; filesortの使用
1 SIMPLE table2 ref FK_first、FK_first_2 FK_first_2 4 table1.id 1
4

1 に答える 1

3

2つの結合を実行し、「OR」をCOUNT()関数に移動してみてください。

すべての行について、これはFK1で一度table2に結合し、次にFK2で再び結合します(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
于 2012-07-13T15:00:18.247 に答える