これは私の最初の投稿なので、1つのリンクしか投稿できないようです。そのため、参照しているサイトを下部にリストしました。一言で言えば、私の目標は、データベースが結果をより速く返すようにすることです。投稿の下部に質問を組み立てるのに役立つように、考えられる限り多くの関連情報を含めるようにしました。
マシン情報
8 processors
model name : Intel(R) Xeon(R) CPU E5440 @ 2.83GHz
cache size : 6144 KB
cpu cores : 4
top - 17:11:48 up 35 days, 22:22, 10 users, load average: 1.35, 4.89, 7.80
Tasks: 329 total, 1 running, 328 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.0%us, 0.0%sy, 0.0%ni, 87.4%id, 12.5%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 8173980k total, 5374348k used, 2799632k free, 30148k buffers
Swap: 16777208k total, 6385312k used, 10391896k free, 2615836k cached
ただし、私たちはmysqlインストールを256GBのRAMを搭載したクラスター内の別のマシンに移動することを検討しています。
テーブル情報
私のMySQLテーブルは次のようになります
CREATE TABLE ClusterMatches
(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
cluster_index INT,
matches LONGTEXT,
tfidf FLOAT,
INDEX(cluster_index)
);
約1800万行あり、1Mの一意のcluster_indexと6Kの一意の一致があります。PHPで生成しているSQLクエリは次のようになります。
SQLクエリ
$sql_query="SELECT `matches`,sum(`tfidf`) FROM
(SELECT * FROM Test2_ClusterMatches WHERE `cluster_index` in (".$clusters."))
AS result GROUP BY `matches` ORDER BY sum(`tfidf`) DESC LIMIT 0, 10;";
ここで、$ clusterには、約3,000のコンマ区切りのcluster_indexの文字列が含まれています。このクエリは約50,000行を使用し、実行に約15秒かかります。同じクエリを再度実行すると、実行に約1秒かかります。
使用法
- テーブルの内容は静的であると見なすことができます。
- 同時ユーザー数が少ない
- 上記のクエリは現在、テーブルで実行される唯一のクエリです
サブクエリ
この投稿[stackoverflow:MySQLでのサブクエリのキャッシュ/再利用] [1]とクエリ時間の改善に基づいて、サブクエリにインデックスを付けることができると思います。
mysql> EXPLAIN EXTENDED SELECT `matches`,sum(`tfidf`) FROM
(SELECT * FROM ClusterMatches WHERE `cluster_index` in (1,2,...,3000)
AS result GROUP BY `matches` ORDER BY sum(`tfidf`) ASC LIMIT 0, 10;
+----+-------------+----------------------+-------+---------------+---------------+---------+------+-------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------------------+-------+---------------+---------------+---------+------+-------+---------------------------------+
| 1 | PRIMARY | derived2 | ALL | NULL | NULL | NULL | NULL | 48528 | Using temporary; Using filesort |
| 2 | DERIVED | ClusterMatches | range | cluster_index | cluster_index | 5 | NULL | 53689 | Using where |
+----+-------------+----------------------+-------+---------------+---------------+---------+------+-------+---------------------------------+
追加情報のこの古い記事[MySQLの最適化:クエリとインデックス] [2]によると、ここで見るのが悪いのは「一時的なものの使用」と「ファイルソートの使用」です。
MySQL構成情報
クエリキャッシュは利用可能ですが、サイズが現在ゼロに設定されているため、事実上オフになっています
mysqladmin variables;
+---------------------------------+----------------------+
| Variable_name | Value |
+---------------------------------+----------------------+
| bdb_cache_size | 8384512 |
| binlog_cache_size | 32768 |
| expire_logs_days | 0 |
| have_query_cache | YES |
| flush | OFF |
| flush_time | 0 |
| innodb_additional_mem_pool_size | 1048576 |
| innodb_autoextend_increment | 8 |
| innodb_buffer_pool_awe_mem_mb | 0 |
| innodb_buffer_pool_size | 8388608 |
| join_buffer_size | 131072 |
| key_buffer_size | 8384512 |
| key_cache_age_threshold | 300 |
| key_cache_block_size | 1024 |
| key_cache_division_limit | 100 |
| max_binlog_cache_size | 18446744073709547520 |
| sort_buffer_size | 2097144 |
| table_cache | 64 |
| thread_cache_size | 0 |
| query_cache_limit | 1048576 |
| query_cache_min_res_unit | 4096 |
| query_cache_size | 0 |
| query_cache_type | ON |
| query_cache_wlock_invalidate | OFF |
| read_rnd_buffer_size | 262144 |
+---------------------------------+----------------------+
[Mysqlデータベースのパフォーマンスターニング][3]に関するこの記事に基づいて、調整する必要のある値は次のとおりです。
- table_cache
- key_buffer
- sort_buffer
- read_buffer_size
- record_rnd_buffer(GROUPBYおよびORDERBY用語の場合)
改善のために特定された領域-MySQLクエリの微調整
- 一致するデータ型を別のテーブルを指すintであるインデックスに変更する[MySQLは、TEXTやBLOBなどの可変長フィールドが含まれている場合、実際に動的行形式を使用します。この場合、並べ替えはディスク上で実行する必要があります。 。解決策は、これらのデータ型を避けることではなく、そのようなフィールドを関連するテーブルに分割することです。] [4]
matches
ステートメント["選択、グループ化、順序付け、または結合しているフィールドのインデックスを作成する必要があります。"] [5]に基づいて、 GROUPBYがより速く発生するように新しいmatch_indexフィールドにインデックスを付けます。
ツール
パフォーマンスを微調整するには、使用する予定です
- 【説明】【6】【出力フォーマット】【7】を参考に
- [ab-ApacheHTTPサーバーベンチマークツール][8]
- [プロファイリング][9]と[ログデータ][10]
将来のデータベースサイズ
目標は、1Mの一意のcluster_index値、1Mの一意の一致値、約0.5秒のクエリへの応答時間を持つ約3,000,000,000のテーブル行を持つことができるシステムを構築することです(必要に応じてramを追加し、データベースをクラスター全体に分散できます)
質問
- クエリがディスクに触れないように、レコードセット全体をRAMに保持したいと思います。データベース全体をMySQLキャッシュに保持すると、memcachedbが不要になりますか?
- データベース全体をMySQLキャッシュに保持しようとすると、永続的になるように設計されていないため、悪い戦略ですか?memcachedbやredisのようなものがより良いアプローチでしょうか?もしそうなら、なぜですか?
- クエリによって作成された一時テーブル「結果」は、クエリが終了すると自動的に破棄されますか?
- InnodbからMyISAMに切り替える必要があります[InnoDBは大量の書き込みに適しているのに対し、大量のデータの読み取りには適しています] [11]?
- [Query Cache Configuration] [12]でキャッシュがゼロとしてオンになっていないように見えますが、2回目に実行したときに、クエリが現在より速く発生するのはなぜですか?
- 「一時的な使用」と「ファイルソートの使用」の発生を排除するためにクエリを再構築できますか?サブクエリの代わりに結合を使用する必要がありますか?
- MySQL[データキャッシュ][13]のサイズをどのように表示しますか?
- 開始点として、table_cache、key_buffer、sort_buffer、read_buffer_size、record_rnd_bufferの値のどのようなサイズを提案しますか?
リンク
- 1:stackoverflow.com/questions/658937/cache-re-use-a-subquery-in-mysql
- 2:databasejournal.com/features/mysql/article.php/10897_1382791_4/Optimizing-MySQL-Queries-and-Indexes.htm
- 3:debianhelp.co.uk/mysqlperformance.htm
- 4:20bits.com/articles/10-tips-for-optimizing-mysql-queries-that-dont-suck/
- 5:20bits.com/articles/10-tips-for-optimizing-mysql-queries-that-dont-suck/
- 6:dev.mysql.com/doc/refman/5.0/en/explain.html
- 7:dev.mysql.com/doc/refman/5.0/en/explain-output.html
- 8:httpd.apache.org/docs/2.2/programs/ab.html
- 9:mtop.sourceforge.net/
- 10:dev.mysql.com/doc/refman/5.0/en/slow-query-log.html
- 11:20bits.com/articles/10-tips-for-optimizing-mysql-queries-that-dont-suck/
- 12:dev.mysql.com/doc/refman/5.0/en/query-cache-configuration.html
- 13:dev.mysql.com/tech-resources/articles/mysql-query-cache.html