12

私はこのようなクエリを実行しています

SELECT parent.field, child.field
FROM parent
JOIN child ON (child.id = parent.id 
    OR child.id = parent.otherid)

ただし、これは非常に遅いです(実際のバージョンでは約100kレコード、および他のテーブルへのJOIN)が、インデックスを試したにもかかわらず

parent.id (PRIMARY),  
parent.otherid,  
child.id (PRIMARY), 
and a composite index of parent.id and parent.otherid

この結合を行うときに、MySQL にこれらのインデックスを使用させることができません。

MySQL は結合ごとに 1 つのインデックスしか使用できないと読みましたが、JOIN に OR 条件が含まれている場合に複合インデックスを使用できるかどうかはどこにもわかりません。

このクエリ参照をインデックスにすることが可能かどうかを知っている人はいますか? もしそうなら、どのように?


私の解決策

(だから、atmの下で私自身の質問に答えさせてくれません)

たくさんの微調整を行い、他のテーブルを結合して集計する機能を保持する、かなり適切なソリューションを思いつきました。

SELECT parent.field, child.field
FROM parent
JOIN (
    SELECT parent.id as parentid, 
    # Prevents the need to union
    IF(NOT ISNULL(parent.otherid) AND parent.otherid <> parent.id, 
       parent.otherid, 
       parent.id) as getdataforid
    FROM parent
    WHERE (condition)
) as foundrecords
    ON foundrecords.parentid = parent.id
JOIN child ON child.id = parent.getdataforid

速度のためには、一時テーブルに配置されるレコードの数を減らすためにサブクエリ内の条件が必要ですが、外部クエリに大量の追加の結合があり、子への結合と親への結合(いくつかの集計を含む)があるため、これ私にとって最もうまくいきました。

多くの場合、ユニオンの方が高速で効果的ですが、親でフィルタリングしているため、子からの追加データ (親の自己参照) が必要なため、ユニオンによって余分な行が発生し、統合できませんでした。親をそれ自体に結合し、外側のクエリで where 条件をエイリアシングするだけで同じ結果が得られる可能性がありますが、これは私にとっては非常にうまく機能します。

UNION ALLの提案をしてくれたJirkaに感謝します。それが私がここにたどり着くきっかけです:)

4

2 に答える 2

11

あなたのクエリは、1 人の子が 2 つの異なる親を持つことを理論的に可能にします。これは、非常に非標準的な用語になります。ただし、データ パターンがそれを不可能にしていると仮定しましょう。

次に、列ごとに 1 つのインデックスを使用して、別のインデックスを使用して同じ結果を取得します。

SELECT parent.field, child.field
FROM parent
JOIN child ON child.id = parent.id 

UNION ALL

SELECT parent.field, child.field
FROM parent
JOIN child ON child.id = parent.otherid
于 2012-06-20T21:24:52.867 に答える
2
EXPLAIN 
SELECT parent.fld, child.fld 
  FROM parent JOIN child ON child.id = parent.id  
 UNION ALL 
SELECT parent.fld, child.fld
  FROM parent JOIN child ON child.id = parent.otherid
   AND parent.otherid <> parent.id

MyISAM エンジンを使用したテーブル:

id  select_type   TABLE       TYPE    possible_keys  KEY      key_len  ref                  ROWS  Extra
1   PRIMARY       parent      ALL     PRIMARY                                               9999
1   PRIMARY       child       eq_ref  PRIMARY        PRIMARY  4        test.parent.id       1
2   UNION         parent      ALL     parent_ix1                                            9999  USING WHERE
2   UNION         child       eq_ref  PRIMARY        PRIMARY  4        test.parent.otherid  1
    UNION RESULT  <union1,2>  ALL

InnoDB エンジンを使用したテーブル:

id  select_type   table       type    possible_keys  key         key_len  ref            rows  Extra
1   PRIMARY       child       ALL     PRIMARY                                            9903
1   PRIMARY       parent      eq_ref  PRIMARY        PRIMARY     4        test.child.id  1
2   UNION         child       ALL     PRIMARY                                            9903
2   UNION         parent      ref     parent_ix1     parent_ix1  5        test.child.id  1     Using where
    UNION RESULT  <union1,2>  ALL   
于 2012-06-20T22:04:03.387 に答える