MySQLデータベースを使用していて、クエリの一部が遅くなりました。クエリ時間は安定していません。ほとんどのクエリは高速ですが、一部のクエリ(読み取りと返されるデータが少ない場合もある)には時間がかかります。
私はベストプラクティスがインデックスの追加またはコードのリファクタリングであることを知っていますが、すでにインデックスが追加されており、コードをリファクタリングしたくありません(少なくとも他のバリアントがある場合)。
8 Gbの空きメモリがあり、CPUの負荷はピーク時に25%にすぎません。だから私はすべてのリソースを使いたいです。
MySQLの設定を調整しようとしていますが、そのような調整の経験がないので、生産性をあまり向上させません。次に例を示します。
# Query_time: 3.019647 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 504
SET timestamp=1313380874;
SELECT COUNT(inboxentities.id) FROM inboxentities WHERE (active=true)AND(deleted=false)AND((to_ = '44219ca4-a657-4909-b30d-a7ba0ed8e4b0'))AND(notification=true);
P. S. inboxentities
には500.000レコードがあります。 index1(idx_to)があります:to_
およびindex2(idx_complex):deleted
、notification
、active
、to_
これは説明の選択の結果です:
+----+-------------+---------------+------+------------------------------------------------+--------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------------+------+------------------------------------------------+--------+---------+-------+------+-------------+
| 1 | SIMPLE | inboxentities | ref | idx_status,idx_statusToname,idx_to,idx_complex | idx_to | 768 | const | 286 | Using where |
+----+-------------+---------------+------+------------------------------------------------+--------+---------+-------+------+-------------+
これは遅いログからの元のクエリです
SELECT COUNT(inboxentities.id) FROM inboxentities
WHERE (active=true)
AND (deleted=false)
AND ((to_ = '44219ca4-a657-4909-b30d-a7ba0ed8e4b0'))
AND (notification=true);
このようなクエリのインデックスを作成する最も効果的な方法は、WHERE句のフィールドをできるだけ多くカバーするインデックスを生成することです。その概念を念頭に置いて作成されたインデックスは カバーするインデックス と呼ばれます。
WHERE句を見てください。
Idx_complexが定義されていますが、idx_complexインデックスが使用されない原因となるクエリの要素がもう1つあります:COUNT(inboxentities.id)句。
あなたはテーブルで何かを数えています。インデックスには、to_以外のテーブルへの参照ポイントはありません。 MySQL Query Optmizerは、最も単純なインデックスであるidx_toを選択します。 MySQLクエリオプティマイザーに必要なカバーインデックス(idx_complex)を選択させるには、テーブルではなくインデックスからCOUNTします。私の提案は、クエリを少し変更することです:
SELECT COUNT(to_) FROM inboxentities
WHERE (active=true)
AND (deleted=false)
AND ((to_ = '44219ca4-a657-4909-b30d-a7ba0ed8e4b0'))
AND (notification=true);
試してみる !!!
UPDATE 2011-08-15 15:16 EDT
一部のユーザーは、my.cnfを変更してストレージエンジンのパフォーマンスニーズを満たすことで、パフォーマンスを大幅に向上させることができます。
MyISAMキーキャッシュとInnoDBバッファープールを設定する必要があります。
これにより、指定したデータセットに適切なサイズのMyISAMキーキャッシュが推奨されます。
SELECT CONCAT(ROUND(KBS/POWER(1024,
IF(PowerOf1024<0,0,IF(PowerOf1024>3,0,PowerOf1024)))+0.4999),
SUBSTR(' KMG',IF(PowerOf1024<0,0,
IF(PowerOf1024>3,0,PowerOf1024))+1,1))
recommended_key_buffer_size FROM
(SELECT LEAST(POWER(2,32),KBS1) KBS
FROM (SELECT SUM(index_length) KBS1
FROM information_schema.tables
WHERE engine='MyISAM' AND
table_schema NOT IN ('information_schema','mysql')) AA ) A,
(SELECT 2 PowerOf1024) B;
これは、指定されたデータセットに適切なサイズのInnoDBバッファープールを推奨します
SELECT CONCAT(ROUND(KBS/POWER(1024,
IF(PowerOf1024<0,0,IF(PowerOf1024>3,0,PowerOf1024)))+0.49999),
SUBSTR(' KMG',IF(PowerOf1024<0,0,
IF(PowerOf1024>3,0,PowerOf1024))+1,1)) recommended_innodb_buffer_pool_size
FROM (SELECT SUM(data_length+index_length) KBS FROM information_schema.tables
WHERE engine='InnoDB') A,
(SELECT 2 PowerOf1024) B;
ちなみに
これを超える場合は、私にメールしてください。
これらの設定を行ったら、recommended_key_buffer_sizeとRecommended_innodb_buffer_pool_sizeの合計数がインストールされているRAMの75%を超えないようにしてください。
UPDATE 2011-08-15 15:35 EDT
サーバーでmysqltuner.plを実行して、DB接続のメモリ使用量を週単位で通知する方法を教えてください。 DB接続ごとのメモリ使用量を制御する設定には、
これらは通常 max_connections で乗算されます。
Mysqltuner.plは、Linuxコマンドラインから次のようにダウンロードできます。
wget mysqltuner.pl
それからの出力は次のようなものです:
$ Perl mysqltuner.pl
>> MySQLTuner 1.2.0 - Major Hayden <[email protected]>
>> Bug reports, feature requests, and downloads at http://mysqltuner.com/
>> Run with '--help' for additional options and output filtering
Please enter your MySQL administrative login: username
Please enter your MySQL administrative password: (password hidden)
-------- General Statistics --------------------------------------------------
[--] Skipped version check for MySQLTuner script
[OK] Currently running supported MySQL version 5.1.47-community-log
[OK] Operating on 64-bit architecture
-------- Storage Engine Statistics -------------------------------------------
[--] Status: +Archive -BDB -Federated +InnoDB -ISAM -NDBCluster
[--] Data in MyISAM tables: 7G (Tables: 6)
[--] Data in InnoDB tables: 2G (Tables: 382)
[!!] Total fragmented tables: 84
-------- Security Recommendations -------------------------------------------
[OK] All database users have passwords assigned
-------- Performance Metrics -------------------------------------------------
[--] Up for: 12d 20h 24m 6s (54M q [49.462 qps], 555K conn, TX: 287B, RX: 95B)
[--] Reads / Writes: 62% / 38%
[--] Total buffers: 9.3G global + 48.2M per thread (1250 max threads)
[!!] Maximum possible memory usage: 68.2G (291% of installed RAM)
[OK] Slow queries: 0% (647/54M)
[OK] Highest usage of available connections: 5% (69/1250)
[OK] Key buffer size / total MyISAM indexes: 256.0M/19.4M
[OK] Key buffer hit rate: 100.0% (51M cached / 10 reads)
[OK] Query cache efficiency: 89.3% (47M cached / 52M selects)
[!!] Query cache prunes per day: 60670
[OK] Sorts requiring temporary tables: 0% (239 temp sorts / 1M sorts)
[!!] Temporary tables created on disk: 47% (1M on disk / 2M total)
[OK] Thread cache hit rate: 99% (103 created / 555K connections)
[OK] Table cache hit rate: 21% (722 open / 3K opened)
[OK] Open file limit used: 0% (70/32K)
[OK] Table locks acquired immediately: 99% (12M immediate / 12M locks)
[OK] InnoDB data size / buffer pool: 2.4G/8.0G
-------- Recommendations -----------------------------------------------------
General recommendations:
Run OPTIMIZE TABLE to defragment tables for better performance
Reduce your overall MySQL memory footprint for system stability
Increasing the query_cache size over 128M may reduce performance
When making adjustments, make tmp_table_size/max_heap_table_size equal
Reduce your SELECT DISTINCT queries without LIMIT clauses
Variables to adjust:
*** MySQL's maximum memory usage is dangerously high ***
*** Add RAM before increasing MySQL buffer variables ***
query_cache_size (> 1G) [see warning above]
tmp_table_size (> 32M)
max_heap_table_size (> 32M)