2017-02-03 20 views
1

私はcaを持つテーブル(T1)を持っています。 500000の非重複レコードは:2つのMySQLテーブルの最適な結合

私はこれらの2つのテーブルを結合したい
ID Entity  
4  Ent4  
5  Ent5 
13 Ent13 
16 Ent16 

(IDに基づいて:4)効率的な方法で次のように:

ID1 Relation ID2 
4  Rel4  13 
5  Rel5  4 
13  Rel13  16 
16  Rel16  5 

私は、プロパティテーブルT1_Propを持っています

Entity Relation Entity 
Ent4  Rel4  Ent13 
Ent5  Rel5  EntEnt4 

この選択文は、うまく動作するJOINを含めて設計しました。しかし、これが最善の方法であるかどうかは分かりません。

select 
    a.entity, 
    r.relation, 
    b.entity 
from T1 as r 
INNER JOIN T1_Prop as a ON a.ID=r.ID1 AND (r.ID1=4 OR r.ID2=4) 
INNER JOIN T1_Prop as b ON b.ID=r.ID2; 
+1

最適化の質問はhttp://codereview.stackexchange.com/に属します – Sirko

+0

何の点でベスト? – Shadow

+0

効率の面で。私はちょうどMySQLを使用したいと思いますし、いくつかの外部ライブラリでそれを改善しようとしていません。 – StaOver

答えて

0

これはSQLをうまく使います。この種のクエリ用に作られています。

には、これを高速化するための2つのインデックスが必要です。彼らは以下のとおりです。

(ID1, ID2, relation) 

(ID2, ID1, relation) 

は、二つのインデックスがOR句を処理するためのものです。これは、私が見る唯一の潜在的なパフォーマンスの問題です。それは、OR操作では、クエリプランナーがあまりにも多くのテーブルスキャンを実行することがあるからです。

あなたのID値の選択をより見やすくするために、これにクエリをリファクタリングしてみてください。あなたがカバーするインデックスを作成した後は、パフォーマンスに問題がある場合は

select a.entity, r.relation, b.entity 
    from T1 as r 
INNER JOIN T1_Prop as a ON a.ID=r.ID1 
INNER JOIN T1_Prop as b ON b.ID=r.ID2 
WHERE (r.ID1=4 OR r.ID2=4) 

その後、

select a.entity, r.relation, b.entity 
    from T1 as r 
INNER JOIN T1_Prop as a ON a.ID=r.ID1 
INNER JOIN T1_Prop as b ON b.ID=r.ID2 
WHERE r.ID1=4 
UNION 
select a.entity, r.relation, b.entity 
    from T1 as r 
INNER JOIN T1_Prop as a ON a.ID=r.ID1 
INNER JOIN T1_Prop as b ON b.ID=r.ID2 
WHERE r.ID2=4 
+0

'UNION ALL'を作成します。これはデフォルトの不要なデュアルダッピングよりも効率的です。 –

0

に再びそれをリファクタリングあなたのクエリは、最初のON句を除いて正常に見えます。条件(r.ID1=4 OR r.ID2=4)は、T1_PropのレコードがT1レコードに参加するルールではありません。それはむしろT1の記録を考慮し、したがってWHERE節に属している状態です。

select 
    a.entity AS entity1, 
    r.relation, 
    b.entity AS entity2 
FROM t1 AS r 
INNER JOIN t1_prop AS a ON a.id = r.id1 
INNER JOIN t1_prop AS b ON b.id = r.id2 
WHERE r.id1 = 4 OR r.id2 = 4; 

これは実行計画を変更しません。 DBMSはこれをまったく同じように実行します。しかし、それは実際の意図を示しているので、よりわかりやすくなります。IDの1つが4の関係を取得し、それらの関係にエンティティを参加させます。この意思を示すために

別のオプションは次のとおりです。

select 
    a.entity AS entity1, 
    r.relation, 
    b.entity AS entity2 
FROM (SELECT * FROM t1 WHERE r.id1 = 4 OR r.id2 = 4) AS r 
INNER JOIN t1_prop AS a ON a.id = r.id1 
INNER JOIN t1_prop AS b ON b.id = r.id2; 

は、一部が読みにくくからサブクエリ、しかし、まあ、他の人がいないことを検討してください。また、クエリが複雑になり、異なるテーブルの集計を処理する場合でも、クリーンなクエリを作成して構築する方法がよくあります。

上記のクエリのどちらも、実際にはどちらのクエリよりも優れているわけではありません。

+0

サブクエリは不要な労力を要します。 –

+0

@Rick James:どちらですか? DBMSは、オプティマイザがうまく動作すれば、2つのクエリの実行計画が同じになるはずです。 MySQLがまだない場合は、最初のクエリまたは2番目のクエリをよりよくサポートできる現在の実装に依存します。たぶん、MySQLは現在のバージョンの派生テーブルに問題があります。知りません。しかし、そうであっても、それは次のバージョンで既に異なっている可能性があります:-) –

+0

'EXPLAIN SELECT ... 'はオプティマイザがスマートになったかどうかを判断するものです。これは約5.7で改善されたものになるでしょう。 –

関連する問題