web-dev-qa-db-ja.com

MySQLデータベースをメモリにキャッシュする

MySQLデータベースが600 MBのWebサイトに問題があります。ウェブサイトが遅すぎる。 MySQLデータベースが大きくなるほど、速度が遅くなることに気づきました。それが5MBだったとき、ウェブサイトは非常に高速でした。大きくなると徐々に遅くなり始め、現在は600MBと非常に遅く、ページのロードに10秒ほどかかります。

上位のプロセスを確認しましたが、高負荷などとは関係ありません。 HDD 7.2k rpmドライブでテストしたため、IOPSにも関係なく、Intel 320 SSDドライブでのテストでも同じ問題が発生したため、クエリ数が多いとは思われません。

WebサイトはWordpress=を使用しており、9つのプラグインがアクティブになっているようです。プラグインの可能性があると人々は言っています...たぶん...しかし、今はデータベース全体をメモリにキャッシュしたいだけですどこから始めて、どのように行うかについてのヘルプと指示を得たいと思います。

16GB RAMおよびi5-2400 4コア@ 3.1GHz。OSはcentos 5.7です。

top - 07:23:57 up 9 days, 12:15, 0 users, load average: 0.09, 0.04, 0.05
Tasks: 162 total, 1 running, 161 sleeping, 0 stopped, 0 zombie
Cpu(s): 8.2%us, 1.0%sy, 0.0%ni, 90.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 16367532k total, 3641628k used, 12725904k free, 612140k buffers
Swap: 1046520k total, 0k used, 1046520k free, 1538896k cached
11
grant tailor

私があなたなら、すべてのデータをInnoDBに切り替えます。テーブルロック/行ロックについては、長い間多くの人が議論してきました。私は常にInnoDBを選択します。ただし、 InnoDB ... CACHINGを選択するもう1つの大きな理由があります

ほとんどの人はMyISAMの方が読み込みが高速であることを自慢していますが、ほとんどの人はMyISAMの多くのキャッシュ(key_buffer_sizeによって設定される)と呼ばれる、.MYIファイルからのインデックスページのみをキャッシュすることを忘れています。データページをキャッシュすることはありません。 32ビットシステムでは公式に最大4GBです。 64ビットの場合、最大8GBが最適です。

InnoDBバッファープールは、データとインデックスページをキャッシュします。使用しているサーバーに応じて、データセット全体をRAMにキャッシュできます。最大80%のInnoDBを調整できますRAMおよびDB接続の場合は10%、OSの場合は10%を残します これは、異なるオペレーティングシステムでも当てはまります

私はこれらのことをDrupalお客様 にすすめています。すばらしい成功を収めています。 Wordpressにも適用されます 同様に。クライアントにDBサポートを提供しましたWordPressと同じです。

いつでも InnoDBのメモリを構成 より効率的にMyISAMを実行できます。常に パフォーマンスのニーズに合わせてInnoDBの週 を行う方法があります。データが大きくなるにつれて、最終的に 要件になる になります。

UPDATE 2011-11-21 11:44 EST

完全なデータセットが十分に小さい場合、mysqlの起動直後に、すべてのテーブルでSELECTクエリを実行できます。

InnoDBまたはMyISAM、あるいはその両方であるすべてのテーブルについて、次のクエリを実行します。

_SELECT DISTINCT
    CONCAT('SELECT ',ndxcollist,' FROM ',
    db,'.',tb,' ORDER BY ',ndxcollist,';') SelectQueryToLoadCache
FROM (
    SELECT
        engine,table_schema db,table_name tb,index_name,
        GROUP_CONCAT(column_name ORDER BY seq_in_index) ndxcollist
    FROM (
        SELECT
            B.engine,A.table_schema,A.table_name,
            A.index_name,A.column_name,A.seq_in_index
        FROM
            information_schema.statistics A INNER JOIN
            (SELECT engine,table_schema,table_name
            FROM information_schema.tables
            WHERE engine IN ('InnoDB','MyISAM')) B
            USING (table_schema,table_name)
        WHERE
            B.table_schema NOT IN ('information_schema','mysql')
            AND A.index_type <> 'FULLTEXT'
        ORDER BY
            table_schema,table_name,index_name,seq_in_index
        ) A
    GROUP BY
        table_schema,table_name,index_name
) AA
ORDER BY
    engine DESC,db,tb
;
_

これにより、参照するすべてのインデックスを呼び出す、実行する必要のあるすべてのSELECTクエリが出力されます。このクエリを/root/MakeSelectQueriesToLoad.sqlというファイルに配置します。スクリプトを実行し、出力/root/SelectQueriesToLoad.sqlを収集します。最後に、それを実行します。

_mysql -u... -p... -AN < /root/MakeSelectQueriesToLoad.sql > /root/SelectQueriesToLoad.sql
mysql -u... -p... < /root/SelectQueriesToLoad.sql
_

これは間違いなくすべてのインデックスページをInnoDBバッファープールとMyISAMキーキャッシュにプリロードします。すべてのデータがInnoDBの場合、2つの変更を行います。

  • WHERE engine IN ('InnoDB','MyISAM')を_WHERE engine='InnoDB'_に置き換えます
  • _CONCAT('SELECT ',ndxcollist,' FROM ',_を_CONCAT('SELECT * FROM ',_に置き換えます

これにより、より多くのデータページがInnoDBバッファープールに追加されます。

最後の注意: InnoDBバッファープールがすべてのInnoDBデータを保持するのに十分な大きさであることを確認してください

10
RolandoMySQLDBA

すでにデータベース全体をメモリにキャッシュしています。問題は、ほぼ確実に、RAM内であってもデータベースの検索にかかる時間です。

ディスクI/O統計を監視します。おそらく、ディスクI/Oがたまにランダムに発生しているだけです。データベースisメモリ内。それは問題ではありません。最初にiostatをインストールする必要があります。プラットフォームやディストリビューションについては言及していませんが、おそらくiostatというパッケージに含まれています。 atopの方が友好的かもしれません。

データベース全体がまだメモリ内にないか、ディスクI/Oが問題であるという証拠を得た後、そうするように言った人はいますか?それ以外の場合、彼らのアドバイスは、あなたを見たことも調べたこともないが、腕に怪我をしてギプスをつけるように言われたことを聞いたばかりの医者に相当します。

2
David Schwartz