2016-05-18 13 views
1

analisi_campo_freeが約100万行のテーブルであることを考慮して、 はmysqlに対してこのクエリを書くための軽量な方法ですか?複数のサブクエリ最適化を使用したmysqlクエリ

select distinct ID_ANALISI from analisi_campo_free 
    where 1=1 
    and ID_ANALISI IN (select ID_ANALISI from analisi_campo_free acf inner join campo_free cf on acf.id_campo_free = cf.id_campo_free where posizione = 1 and valore = '06/11/2015') 
    and ID_ANALISI IN (select ID_ANALISI from analisi_campo_free acf inner join campo_free cf on acf.id_campo_free = cf.id_campo_free where posizione = 3 AND valore='vvvvvv'); 

おかげ


id select_type table partitions type possible_keys key key_len ref rows filtered Extra 
1 SIMPLE cf  index PRIMARY ID_LABORATORIO 4  6 16.67 Using where; Using index; Using temporary; Start temporary 
1 SIMPLE cf  index PRIMARY ID_LABORATORIO 4  6 16.67 Using where; Using index; Using join buffer (Block Nested Loop) 
1 SIMPLE acf  ALL ID_ANALISI,FK_ANALISI_CAMPO_FREE_CAMPO_FREE    1054163 11.11 Using where; Using join buffer (Block Nested Loop) 
1 SIMPLE acf  eq_ref ID_ANALISI,FK_ANALISI_CAMPO_FREE_CAMPO_FREE ID_ANALISI 5 elettroforesi.acf.ID_ANALISI,elettroforesi.cf.ID_CAMPO_FREE 1 11.11 Using where 
1 SIMPLE analisi_campo_free  ref ID_ANALISI ID_ANALISI 4 elettroforesi.acf.ID_ANALISI 1 100 Using index; End temporary 

クエリを説明

select distinct ID_ANALISI from analisi_campo_free 
where 1=1 
and ID_ANALISI IN (select ID_ANALISI from analisi_campo_free acf inner join campo_free cf on acf.id_campo_free = cf.id_campo_free where posizione = 1 and valore like 'irene%') 
and ID_ANALISI IN (select ID_ANALISI from analisi_campo_free acf inner join campo_free cf on acf.id_campo_free = cf.id_campo_free where posizione = 3 AND valore like 'antonio%'); 

が、これに約2.3秒を必要とするクエリ

SELECT acf.ID_ANALISI, COUNT(DISTINCT cf.posizione, acf.valore) AS matches 
FROM analisi_campo_free AS acf 
INNER JOIN campo_free AS cf ON acf.id_campo_free = cf.id_campo_free 
WHERE (posizione = 1 AND valore like 'irene%') 
    OR (posizione = 3 AND valore like 'antonio%') 
GROUP BY acf.ID_ANALISI 
HAVING matches = 2; 

が、これに約1.3秒

id select_type table partitions type possible_keys key key_len ref rows filtered Extra 
1 SIMPLE cf  index PRIMARY ID_LABORATORIO 4  6 30.56 Using where; Using index; Using temporary; Using filesort 
1 SIMPLE acf  ALL ID_ANALISI,FK_ANALISI_CAMPO_FREE_CAMPO_FREE    1054163 20.99 Range checked for each record (index map: 0x6) 

指標である説明が必要です。今、私は私のようなを必要と知っているので、

Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment 
analisi_campo_free 0 PRIMARY 1 ID_ANALISI_CAMPO_FREE A 1054159    BTREE  
analisi_campo_free 0 ID_ANALISI 1 ID_ANALISI A 1049622    BTREE  
analisi_campo_free 0 ID_ANALISI 2 ID_CAMPO_FREE A 1049622    BTREE  
analisi_campo_free 1 FK_ANALISI_CAMPO_FREE_CAMPO_FREE 1 ID_CAMPO_FREE A 1    BTREE  


Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment 
campo_free 0 PRIMARY 1 ID_CAMPO_FREE A 6    BTREE  
campo_free 0 DESCRIZIONE 1 DESCRIZIONE A 6    BTREE  
campo_free 0 ID_LABORATORIO 1 ID_LABORATORIO A 1    BTREE  
campo_free 0 ID_LABORATORIO 2 POSIZIONE A 6    BTREE  
campo_free 0 ID_LABORATORIO 3 UTILIZZATO A 6   YES BTREE  

私は、カップルでのクエリを考慮していませんでした。 最後に、querydslで簡単に翻訳できるので、最初のクエリを使用します。あなたの助けあなたが使用することができ

+0

パフォーマンスに関する質問には、 'EXPLAIN ANALYZE'と、テーブルサイズ、インデックス、現在の時間パフォーマンス、欲求時間などの情報が含まれている必要があります。'スロー 'は相対的な用語で、比較のためには本当の値が必要です。 [** MySQL **](http://dba.stackexchange.com/questions/15371/how-do-i-get-the-execution-plan-for-a-view) –

+0

@JuanCarlosOropezaだからあなたはあなたが説明からの値を見ずに問題の質問を書く良い方法を見つけることができないことを教えてください。 *大声で拍手を送る* –

+0

@RahulSharma最適化の最も重要な部分はインデックスです。だから、あなたは問題の5%を解決しようとしている時間の80%を費やすことができます。しかし、私はむしろ効率的に働きます。あなたは 'ラッド'答えをチェックすることができます、素晴らしい解決策ですが、インデックスが適切なセットがまだ悪い性能を持っていない場合。 –

答えて

1

ため ありがとう:

SELECT ID_ANALISI 
FROM analisi_campo_free acf 
JOIN campo_free cf 
    ON acf.id_campo_free = cf.id_campo_free 
WHERE (posizione,valore) IN ((1,'06/11/2015'),(3,'vvvvvv')) 
GROUP BY ID_ANALSI 
HAVING SUM(posizione = 1 AND valore = '06/11/2015') > 0 
    AND SUM(posizione = 3 AND valore='vvvvvv') > 0; 
+0

外部ANDをORに変更したときと同じ結果を返すことはありません。 – Uueerdo

+0

@Uueerdo良い点、修正。 – lad2025

1

サブクエリの句は、通常のMySQLの貧しいパフォーマー、特に相関副問合せですWHEREインチこれにより、関連付けられたcampo_freeレコードが検索され、条件に一致する異なるポジション、偶数ペアがカウントされます。 HAVINGは、両方が結果に含まれているID_ANALISIのみを保証します。

SELECT acf.ID_ANALISI, COUNT(DISTINCT cf.posizone, cf.valore) AS matches 
FROM analisi_campo_free AS acf 
INNER JOIN campo_free AS cf ON acf.id_campo_free = cf.id_campo_free 
WHERE (posizione = 1 AND valore = '06/11/2015') 
    OR (posizione = 3 AND valore='vvvvvv'); 
GROUP BY acf.ID_ANALISI 
HAVING matches = 2 
; 

DISTINCTがCOUNTではなく、 posizone、valoreのペアが各id_campo_free値に対して一意でない場合、2つ(1、 '6/11/2015')または(3、 'vvvvvv')の一致を持つID_ANALISIも最終結果に含めることができます。