web-dev-qa-db-ja.com

現在のサーバーリソースを使用してMySQLのパフォーマンスをどのように向上させますか?

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):deletednotificationactiveto_

これは説明の選択の結果です:

+----+-------------+---------------+------+------------------------------------------------+--------+---------+-------+------+-------------+
| 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 |
+----+-------------+---------------+------+------------------------------------------------+--------+---------+-------+------+-------------+
7
Xupypr MV

これは遅いログからの元のクエリです

SELECT COUNT(inboxentities.id) FROM inboxentities
WHERE (active=true)
AND (deleted=false)
AND ((to_ = '44219ca4-a657-4909-b30d-a7ba0ed8e4b0'))
AND (notification=true);

このようなクエリのインデックスを作成する最も効果的な方法は、WHERE句のフィールドをできるだけ多くカバーするインデックスを生成することです。その概念を念頭に置いて作成されたインデックスは カバーするインデックス と呼ばれます。

WHERE句を見てください。

  • 'active'はtrueまたはfalse(2つの値)です。そのフィールドのみのインデックスが偏っています。
  • 'deleted'はtrueまたはfalse(2つの値)です。そのフィールドのみのインデックスが偏っています。
  • 'notification'はtrueまたはfalse(2つの値)です。そのフィールドのみのインデックスが偏っています。
  • 「to_」は、インデックスを付けて絞り込む価値のある値です。

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;

ちなみに

  • (SELECT 0 PowerOf1024)バイトで回答を生成します
  • (SELECT 1 PowerOf1024)回答をKBで生成します
  • (SELECT 2 PowerOf1024)答えをMBで生成します
  • (SELECT 3 PowerOf1024)答えをGBで生成します

これを超える場合は、私にメールしてください。

これらの設定を行ったら、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)
6
RolandoMySQLDBA