2012-03-30 17 views
8

myisamで元々保存されていた3000万を超えるレコードを持つmysqlテーブルがあります。ここでは、テーブルの説明です:MysqlのInnodbとMyisamのパフォーマンスの差

describe_table

私は、一般的に完了するまでに約30秒かかります。このテーブルに対して次のクエリを実行します。データベースやディスクのキャッシュを避けるために毎回@eidを変更します。

select count(fact_data.id) 
    from fact_data 
    where [email protected] 
     and fact_data.metric_id=1 

私は、同じクエリは今二の下で、私はクエリを実行するごとに一回で返し、その後、他の変更を行わずにInnoDBテーブルにこのテーブルを変換します。キャッシュを避けるために@eidをランダムに設定しても、クエリは1秒以内に戻ります。

パフォーマンスの劇的な改善を説明しようとしているが、何も思い付かなかった2つのストレージタイプの違いを研究してきました。実際、私が読んだことの多くはMyisamがより速くなければならないことを示しています。

私が実行しているクエリは、テスト時に他のプロセスがデータベースにアクセスしていないローカルデータベースに対して実行されます。

答えて

15

これは驚くほど大きなパフォーマンスの違いですが、私は貢献しているかもしれないいくつかのことを考えることができます。

MyISAMは、歴史的にInnoDBよりも速いと見なされていましたが、最近のバージョンのInnoDBでは、はるかに小さいユースケースの場合に当てはまります。 MyISAMは通常、読み取り専用テーブルのテーブルスキャンの方が高速です。他のほとんどのユースケースでは、InnoDBの高速化が一般的です。頻繁に何倍も速くなります。テーブルロックは、MyISAMのほとんどの私のMySQLの使用の中で死にかけています。

MyISAMはキーバッファにインデックスをキャッシュします。おそらく、キーバッファーを小さすぎると設定して、いくらか大きなテーブルのインデックスを効果的にキャッシュすることはできません。

MyISAMは、OSディスクキャッシュ内の.MYDファイルからテーブルデータをキャッシュするOSに依存します。 OSのメモリが不足している場合、ディスクキャッシュのダンプが開始されます。それはディスクからの読み取りを強制する可能性があります。

InnoDBはインデックスとデータを両方とも独自のメモリバッファにキャッシュします。 OS Xではサポートされていませんが、innodb_flush_methodをO_DIRECTに設定すると、ディスクキャッシュも使用しないようにOSに指示できます。

通常、InnoDBはデータとインデックスを16kbページでバッファします。クエリ間で@eidの値をどのように変更するかに応じて、以前のクエリのディスク読み込みのために、1つのクエリのデータを既にキャッシュしている可能性があります。

インデックスが同じであることを確認してください。 MySQLがインデックスを使用しているかどうかを確認するには、説明を使用します。 show create tableやshow indexes fromの代わりにdescribeの出力を含めたので、entity_idが複合インデックスの一部であるかどうかはわかりません。コンポジットインデックスの最初の部分でない場合は、使用されません。あなたは、MySQLの比較的最近のバージョンを使用している場合は

、クエリを実行する前に、次のコマンドを実行します。

セットプロファイリング= 1;

これによりセッションのクエリプロファイリングが有効になります。クエリを実行した後、

プロファイルを実行します。

これは、利用可能なプロファイルのクエリ一覧を表示します。私はそれがデフォルトで最後の20を保持すると思います。クエリが最初のものだったとします。

クエリ1のプロファイルを表示します。

次に、クエリを実行する各段階の期間が表示されます。これは、クエリを遅くする原因(たとえば、テーブルのロック、ソート、一時テーブルの作成など)を判断する場合に非常に役立ちます。

6

私の最初の疑念は、元のMyISAMテーブルやインデックスが時間の経過とともに断片化し、パフォーマンスが低下してゆくことです。 InnoDBテーブルには、すべてのデータがすでに格納されているため、同じ問題は発生しません(すべてがディスクに順次格納されます)。

この理論は、MyISAMテーブルを再構築することでテストできます。これを行う最も簡単な方法は、「NULL」のALTER TABLEステートメントを使用することです。

ALTER TABLE mytable ENGINE = MyISAM; 

次に、パフォーマンスが良いかどうかを確認します。

データベース自体が単にMyISAMではなくInnoDBのパフォーマンスに調整されている可能性があります。たとえば、InnoDBはinnodb_buffer_pool_size parameterを使用して、キャッシュされたデータとインデックスをメモリに格納するために割り当てられるメモリの量を知ります。しかし、MyISAMはkey_bufferパラメータを使用します。データベースに大きなinnodbバッファプールと小さなキーバッファがある場合、InnoDBのパフォーマンスはMyISAMのパフォーマンスよりも優れています(特に大きなテーブルの場合)。

+0

新しいMyISAMテーブルを作成し、そのテーブルに対してクエリを計るという、かなり簡単なテストで、この推測を確認できました。 –

1

インデックスの定義とは、インデックスフィールドを使用しないと思われるMyISAMのインデックスを作成する方法があります。

関連する問題