2016-05-17 7 views
0

でクエリフィールドに追加することによって、私は、MySQLの以下のインデックスの挙動を理解することはできません、MYSQLインデックス速くないインデックス

次のクエリでは、第二25を取り、64776を返します。

SELECT count(*) 
FROM Analisi analisi0_ 
    INNER JOIN Paziente paziente3_ ON analisi0_.ID_PAZIENTE = paziente3_.ID_PAZIENTE 
WHERE 1 = 1 
AND paziente3_.nome LIKE 'MARIA%'; 

次のクエリは、7秒を取り、常に64776返す:

SELECT count(*) 
FROM Analisi analisi0_ 
    INNER JOIN Paziente paziente3_ ON analisi0_.ID_PAZIENTE = paziente3_.ID_PAZIENTE 
WHERE 1 = 1 
AND paziente3_.nome LIKE 'MARIA%' 
AND (paziente3_.DATA_NASCITA > 0 || paziente3_.DATA_NASCITA is NULL); 

が最初のスロークエリのための説明です:

Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment 
analisi 0 PRIMARY 1 ID_ANALISI A 1454102    BTREE  
analisi 1 FK_ANALISI_PAZIENTE 1 ID_PAZIENTE A 1454102    BTREE  
analisi 1 FK_ANALISI_SESSIONE 1 ID_SESSIONE A 56498    BTREE  
analisi 1 FK_ANALISI_PATOLOGICO 1 ID_PATOLOGICO A 1   YES BTREE  
analisi 1 FK_ANALISI_TIPO_VALIDAZIONE 1 ID_TIPO_VALIDAZIONE A 1    BTREE  
analisi 1 FK_ANALISI_UTENTE_MODIFICA 1 ID_UTENTE_MODIFICA A 1   YES BTREE  
analisi 1 FK_ANALISI_UTENTE_VALIDAZIONE 1 ID_UTENTE_VALIDAZIONE A 1   YES BTREE  
analisi 1 FK_ANALISI_UTENTE_CANCELLAZIONE 1 ID_UTENTE_CANCELLAZIONE A 1   YES BTREE  
analisi 1 FK_ANALISI_ANALISI_LINK 1 ID_ANALISI_LINK A 1   YES BTREE  
analisi 1 FK_ANALISI_ANALISI_IFE 1 ID_ANALISI_IFE A 227   YES BTREE  
analisi 1 FK_ANALISI_ANALISI_NOTA 1 ID_ANALISI_NOTA A 17132   YES BTREE  
analisi 1 FK_ANALISI_ANALISI_DATI 1 ID_ANALISI_DATI A 1454102   YES BTREE  
analisi 1 IDX_CAMPIONE 1 CAMPIONE A 102648   YES BTREE  
analisi 1 IDX_REPARTO 1 REPARTO A 132   YES BTREE 

私は本当にすることができます:

id select_type table partitions type possible_keys key key_len ref rows filtered Extra 
1 SIMPLE paziente3_  range PRIMARY,IDX_NOME,IDX_DATA_NASCITA IDX_NOME 123  178176 50.07 Using index condition; Using where; Using MRR 
1 SIMPLE analisi0_  ref FK_ANALISI_PAZIENTE FK_ANALISI_PAZIENTE 4 elettroforesi_light.paziente3_.ID_PAZIENTE 1 100 Using index 

インデックステーブルの上にPAZIENTE:

id select_type table partitions type possible_keys key key_len ref rows filtered Extra 
1 SIMPLE paziente3_  range PRIMARY,IDX_NOME IDX_NOME 123  178176 100 Using where; Using index 
1 SIMPLE analisi0_  ref FK_ANALISI_PAZIENTE FK_ANALISI_PAZIENTE 4 elettroforesi_light.paziente3_.ID_PAZIENTE 1 100 Using index 

2番目のクエリのために説明している間は、

Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment 
paziente 0 PRIMARY 1 ID_PAZIENTE A 1404534    BTREE  
paziente 1 IDX_COGNOME 1 COGNOME A 161711   YES BTREE  
paziente 1 IDX_NOME 1 NOME A 169702   YES BTREE  
paziente 1 IDX_DATA_NASCITA 1 DATA_NASCITA A 15513   YES BTREE  
paziente 1 IDX_SESSO 1 ID_SESSO A 1    BTREE  
paziente 1 FK_PAZIENTE_SPECIE 1 ID_SPECIE A 1    BTREE  

とテーブルANALISIのインデックスueryがIDX_NOMEを使用し、IDX_NOMEがDATA_NASCITAを含まない場合、結果がより良い理由を理解してください。 Like以来

+0

両方のクエリをさまざまな順序で複数回実行し、テスト中に断続的にシステムを再起動しましたか?基礎となるOSによるMySQLのクエリ結果とディスク内容の両方のキャッシュの利点を過小評価しないでください。 – Uueerdo

+0

はい、少なくとも20回テストされたripetitiveな動作です – Etantonio

+0

'インデックス条件の使用と' MRRの使用 '。追加のテストを追加すると、明白な理由がないため、クエリプランが変更され、さらに2つの最適化が行われます。これらのテーブルはInnoDBですか?もしそうなら、SELECT @@ INNODB_BUFFER_POOL_SIZE;から何を得るのですか? –

答えて

0

は、2番目のクエリではそこフィルターはあなたの結果のより少ない数を与える最初に実行されますので、クエリに複数のフィルタされた後、それらの結果の上に塗布されたいと、mysqlのでコストのかかる作業です。最初のクエリで最初のクエリフィルタ月後の結果は、クエリのANDフィルタとして

(paziente3_.DATA_NASCITA > 0 || paziente3_.DATA_NASCITA is NULL); 

を追加するときに、第2のクエリに還元されるレコードの数より多くを含んでいるので

+0

しかし、 "and(paziente3_.DATA_NASCITA> 0 || paziente3_.DATA_NASCITAがNULLです)"は私の考え方では真のフィルタではありません。 – Etantonio

+0

@Etantonio \t DATA_NASCITAに値が含まれていてもNULLでないか0より大きい値がある可能性があります。両方のクエリから同様の部分を削除するとクエリを実行すると、両方のクエリの数の違いを簡単に確認できます。両方とも異なる結果を持つでしょう。 –

+0

次の2つのクエリは同じ結果を持っています:1408146、 1 = 1のpazienteからの選択カウント(*) AND(paziente.DATA_NASCITA> 0 || paziente.DATA_NASCITAがNULLです); pazienteからの選択カウント(*)。 条件のフィルタがないようです。 AND(paziente.DATA_NASCITA> 0 || paziente.DATA_NASCITAがNULLです)。 お時間をいただきありがとうございます。 pazienteからの選択カウント(*)。 – Etantonio

0

はそれがすべて178K(または多分のみ64K)ID_PAZIENTEの値を収集することをhttps://dev.mysql.com/doc/refman/5.6/en/mrr-optimization.html

注を参照してください、他のテーブルへのルックアップを行い、その後、それらをソートします。

これは、innodb_buffer_pool_sizeが小さすぎることを意味します。この設定は、の約70%である必要があります。 RAM。可能であればそれを増やしてください。ほとんどのクエリを高速化し、おそらくこれらのクエリの両方を7秒未満で実行させるでしょう。

+0

小規模な訂正:「ソートしてから、別のテーブルに検索します」その説明はバッチキーアクセス(BKA)に適しています。 MRRの場合、ソートはDATA_NASCITAの条件を評価するために基本表の行を検索する前に行われます。ただし、この場合、他の表に使用される索引が最初の表の主キーでソートされるため、MRRはBKAと同じ効果を持ちます。つまり、最初のテーブルのMRRはFK_ANALISI_PAZIENTEインデックスへのアクセスを順番に行います。私は、インデックス・アクセスに関するIOの問題がある場合、バッファ・プールが小さすぎることに同意します。 – oysteing

関連する問題