2012-05-10 15 views
1

2つのMySQLテーブルを結合してビューとして格納したいので、2つのテーブルをクエリする代わりに、アプリケーションでこのビューを扱うことができます。しかし、この見方は非常に遅いことが起こります。MySQLビューの最適化

これは私のテーブルです:

CREATE TABLE spectrumsets (
    setid INT(11) NOT NULL, 
    timestampdt INT(11) NULL DEFAULT NULL, 
    timestampd INT(10) UNSIGNED NOT NULL, 
    timestampt INT(10) UNSIGNED NOT NULL, 
    device INT(11) NOT NULL, 
    methodname VARCHAR(50) NOT NULL, 
    PRIMARY KEY (setid), 
    UNIQUE INDEX setid_idx (setid), 
    UNIQUE INDEX timestamp_device_idx (timestampd, timestampt, device), 
    INDEX device_fk (device), 
    INDEX timestampd_idx (timestampd), 
    CONSTRAINT device_fk FOREIGN KEY (device) 
     REFERENCES spectrumdevices (deviceid) 
) 
COLLATE='utf8_general_ci' 
ENGINE=InnoDB 

CREATE TABLE spectrumdata (
    valueid INT(11) NOT NULL AUTO_INCREMENT, 
    spectrumset INT(11) NOT NULL, 
    wavelength DOUBLE NULL DEFAULT NULL, 
    intensity DOUBLE NULL DEFAULT NULL, 
    PRIMARY KEY (valueid), 
    INDEX spectrumset_idx (spectrumset), 
    CONSTRAINT spectrumset_fk FOREIGN KEY (spectrumset) 
     REFERENCES spectrumsets (setid) 
) 
COLLATE='utf8_general_ci' 
ENGINE=InnoDB 

そして、これが私の見解です:私のマシン上

SELECT spectrumsets.timestampd,spectrumsets.timestampt,spectrumsets.device, 
    spectrumdata.wavelength,spectrumdata.intensity 
FROM spectrumdata INNER JOIN spectrumsets ON spectrumdata.spectrumset= 
    spectrumsets.setid 
WHERE spectrumdata.wavelength>0 
ORDER BY spectrumsets.timestampd,spectrumsets.timestampt,spectrumsets.device, 
    spectrumdata.wavelength 

select count(*)は82923705のレコードに385.516秒と結果を取るので、かなり大規模なデータセット

私はすでにこのlinkを見つけましたが、何が間違っているかを完全に理解していません。

UPDATE:

EXPLAINは、この結果を与える:

"id","select_type","table","type","possible_keys","key","key_len","ref","rows","Extra" 
"1","SIMPLE","spectrumsets","index","PRIMARY,setid_idx","timestamp_device_idx","12",NULL,"327177","Using index; Using temporary; Using filesort" 
"1","SIMPLE","spectrumdata","ref","spectrumset_idx","spectrumset_idx","4","primprod.spectrumsets.setid","130","Using where" 
+2

あなたは、EXPLAINを使用していますか? –

+0

'analyze tables spectrumdata spectrumsets'を実行しても何か違いはありますか? – Bohemian

+1

あなたのbuffer_pool_sizeは何ですか?データセットがメモリに収まらないように見えるので、InnoDBはおそらくフルテーブルスキャンを実行している間にディスクをレイプしています。 –

答えて

2

説明は、クエリが(良いです)参加のための指標を打つが、その後の一時テーブルやファイルの並べ替えを使用していることを示唆していますクエリの残りの部分。

これは、2つの理由からです:

  • 句は、ORDER BY句は、コメントでは、インデックス

を打っていない、あなたが言うインデックス

  • に当たっていませんwhere句を削除すると大きな改善につながります。スペクトルセット、波長に複合インデックスが必要であることを示唆しています。波長が適切な数の可能な値を持っていると仮定します(10の値であれば、インデックスは何もしません)。

    "order by"句をビューから外しておくと、処理時間が大幅に短縮されるはずです。また、ビューではなくクエリ抽出データによってソート順を決定できる場合があります。私は、ほとんどのクエリがデータについて非常に選択的になると思っています - タイムスタンプはいくつかあります。ビューに注文を埋め込むことで、毎回ソートするための価格を支払うことになります。

    実際にビューで「注文」を行う必要がある場合は、すべてのフィールドを「注文順」の順番で、前に結合を含むインデックスを作成します。例えば:

    UNIQUE INDEXのtimestamp_device_idx(set_id、timestampd、timestampt、デバイス)、

  • +0

    +1。これは正解ですが、MySQL 5です。0+は[index merge](http://dev.mysql.com/doc/refman/5.0/en/index-merge-optimization.html)を使用して複数のインデックスを使用できます。私はその声明を反対に削除するか、または明確にします。また、その複合インデックスでは、インデックスに対して範囲を使用すると、残りの部分が無効になるため、範囲を使用する列を配置します(この場合は波長列です(「WHERE波長> 0」を参照)。それ以外の場合は、最初に最も大きな基数を持つ列を配置します。 –

    +0

    いくつかのテストを行いましたか?ORDER BY句を削除すると、約385秒の実行時間が約285秒に短縮されますが、WHERE句も約48秒に短縮されます。ですから、私はORDER BY句を呼び出し側のアプリケーションに移す必要があると思いますが、WHERE句も移動してください。私の場合は問題ではありませんが、何が起こっているのかまだ十分に理解していません:-(innodb_buffer_pool_sizeで何かを持つことになりますが、ビューのSQLステートメントの作成にもなります) – waanders

    +0

    これは、問題の原因となっている句、それに応じて回答を編集します –

    関連する問題