web-dev-qa-db-ja.com

MySQLパフォーマンスの問題-断続的に遅いクエリ

いくつかの場所で約50人のスタッフが使用するイントラネットアプリケーションを管理しています。アプリケーションはWindows Server 2008でホストされていますVM with 8GB RAMおよびMySQL(5.5)がIISと同じサーバーで実行されています。

スロークエリロギングを有効にしていて、特定のクエリが断続的に遅いことに気付きました。たとえば、一部のクエリは13秒かかるとログに記録していますが、マシン(またはサーバー)のMySQLクライアントで同じクエリを試行すると、高速(約0.1秒)です。

数週間前、私はmysqlcheck --auto-repair --optimize --all-databasesを実行しましたが、それは物事を助けるように見えました-クエリログはほとんど密集してはいませんでした。ただし、今週はさまざまなクエリが断続的に長時間かかるため、以前の状態に戻りました。

スロークエリログが今朝8.3秒かかると記録したクエリが1つあります。 CLIから5〜6回実行し、2回は〜2秒で、残りは0.2秒未満でした。

遅いクエリはすべてSELECTですが、1秒以上かかる非常に少数のINSERTを目にしました。

すべてのテーブルはInnoDBです。 show variablesで示されるInnoDB変数は次のとおりです。

+---------------------------------+------------------------+ | Variable_name | Value | +---------------------------------+------------------------+ | have_innodb | YES | | ignore_builtin_innodb | OFF | | innodb_adaptive_flushing | ON | | innodb_adaptive_hash_index | ON | | innodb_additional_mem_pool_size | 27262976 | | innodb_autoextend_increment | 8 | | innodb_autoinc_lock_mode | 1 | | innodb_buffer_pool_instances | 1 | | innodb_buffer_pool_size | 2097152000 | | innodb_change_buffering | all | | innodb_checksums | ON | | innodb_commit_concurrency | 0 | | innodb_concurrency_tickets | 500 | | innodb_data_file_path | ibdata1:10M:autoextend | | innodb_data_home_dir | | | innodb_doublewrite | ON | | innodb_fast_shutdown | 1 | | innodb_file_format | Antelope | | innodb_file_format_check | ON | | innodb_file_format_max | Antelope | | innodb_file_per_table | OFF | | innodb_flush_log_at_trx_commit | 1 | | innodb_flush_method | | | innodb_force_load_corrupted | OFF | | innodb_force_recovery | 0 | | innodb_io_capacity | 2000 | | innodb_large_prefix | OFF | | innodb_lock_wait_timeout | 50 | | innodb_locks_unsafe_for_binlog | OFF | | innodb_log_buffer_size | 13631488 | | innodb_log_file_size | 652214272 | | innodb_log_files_in_group | 2 | | innodb_log_group_home_dir | .\ | | innodb_max_dirty_pages_pct | 75 | | innodb_max_purge_lag | 0 | | innodb_mirrored_log_groups | 1 | | innodb_old_blocks_pct | 37 | | innodb_old_blocks_time | 0 | | innodb_open_files | 300 | | innodb_purge_batch_size | 20 | | innodb_purge_threads | 0 | | innodb_random_read_ahead | OFF | | innodb_read_ahead_threshold | 56 | | innodb_read_io_threads | 64 | | innodb_replication_delay | 0 | | innodb_rollback_on_timeout | OFF | | innodb_rollback_segments | 128 | | innodb_spin_wait_delay | 6 | | innodb_stats_method | nulls_equal | | innodb_stats_on_metadata | ON | | innodb_stats_sample_pages | 8 | | innodb_strict_mode | OFF | | innodb_support_xa | ON | | innodb_sync_spin_loops | 30 | | innodb_table_locks | ON | | innodb_thread_concurrency | 0 | | innodb_thread_sleep_delay | 10000 | | innodb_use_native_aio | ON | | innodb_use_sys_malloc | ON | | innodb_version | 1.1.8 | | innodb_write_io_threads | 64 | +---------------------------------+------------------------+

この時点で何を見たり監視したりする必要がありますか? IISに対するメモリまたはディスクI/Oリソースの問題がある場合に専用データベースサーバーを取得する可能性を検討していますが、これは現実的ではない可能性があります。

商業上の機密保持の理由から、ここで特定のクエリを共有するのは気が進まないため、役に立たない可能性があります。

追加情報

MySQL Tuner for Windowsを実行して、次の結果を得ました。

-8000 MBの物理メモリを想定-12286 MBのスワップスペースを想定-現在実行中のサポートされているMySQLバージョン5.5.24ログ-InnoDBエンジンがインストール済み-InnoDBテーブル内のデータ:575M(テーブル:194)-断片化されたテーブルの合計:194-すべてのデータベースユーザーにはパスワードが割り当てられています-最大:1d 7h 44m 38s(982K q [8.000 qps]、41K conn、TX:15G、RX:839M)-読み取り/書き込み:98%/ 2%-合計バッファー:2.6Gグローバル+ 960.0スレッドあたりK(最大400スレッド)-可能な最大メモリ使用量:3.0G(インストールされているRAMの38%)-遅いクエリ:1%(476/982K)-利用可能な接続の最大使用量:2%(7/400)-キーバッファーサイズ/合計MyISAMインデックス:641.0M/263.0K-キーバッファーヒット率:99%(2Mキャッシュ/ 7読み取り)-クエリキャッシュが無効-一時テーブルを必要とするソート:6%(5K一時ソート/ 102Kソート)-結合インデックスなしで実行:7320-ディスク上に作成された一時テーブル:38%(ディスク上で31K /合計84K)-スレッドキャッシュヒット率:99%(7作成/ 41K接続)-テーブルキャッシュヒット率:1%(155オープン/ 9K開いた)-使用されるオープンファイルの制限:0%(3/4K)-すぐに取得されるテーブルロック:100%(1M即時/ 1Mロック)-InnoDBデータサイズ/バッファプール:575.2M/2.0G-最適化テーブルを実行してテーブルを最適化し、パフォーマンスを向上-常にインデックスを使用するように結合クエリを調整します-調整を行う場合は、tmp_table_size/max_heap_table_sizeを等しくします-LIMIT句なしでSELECT DISTINCTクエリを減らします-ファイル記述子の制限を回避するためにtable_cacheを徐々に増やします-query_cache_size(> = 8M)-join_buffer_size(> 128.0K 、または常に結合でインデックスを使用する)-tmp_table_size(> 64M)-max_heap_table_size(> 16M)-table_cache(> 256)

2015年10月23日更新

月曜日の夜に、いくつかの構成変数を調整しました-join_buffer_sizesort_buffer_sizetable_open_cache。火曜日に、私は1時間かけてデータベース全体を調べ、結合で使用されているほとんどすべての列にインデックスを追加しました(いくつかを逃した可能性があります)。次に、アプリ内の変更をいくつか行った結果、a)クエリが改善され、b)(比較的)トラフィックの多いページでのクエリが減少しました。

変更前、月曜日の遅いクエリログには、1秒を超える474クエリがありました。火曜日のインデックス作成後のクエリは220秒で、1秒以上でした。木曜日までに、アプリの変更により、1秒を超えるクエリ数は110に減少しました。今朝、アプリのアップデートを行った後、今日はまた下がると予想しています。まだ、EXPLAINプロファイルが適切で、断続的に遅いクエリがいくつかあります。更新されたチューナーの出力は以下のとおりです。最新のアプリから適切なサイズのサンプルを収集した後、EXPLAINおよびSHOW CREATE TABLEを使用していくつかのサンプルクエリを提供します。

更新されたチューナー出力。今朝MySQLを再起動したので、元の投稿ほど多くのデータがありません。何らかの理由で、インデックスなしで実行された結合の数が出力されなくなりました...

  • 8000 MBの物理メモリを想定
  • 12286 MBのスワップ領域を想定
  • 現在サポートされているMySQLバージョン5.5.24-logを実行している
  • インストールされたアーカイブエンジン
  • Berkeley DBエンジンがインストールされていません
  • 統合エンジンがインストールされていません
  • インストールされたInnoDBエンジン
  • ISAMエンジンがインストールされていません
  • NDBCLUSTERエンジンがインストールされていません
  • InnoDBテーブル内のデータ:576M(テーブル:192)
  • MyISAMテーブルのデータ:1M(テーブル:19)
  • 断片化されたテーブルの合計:192
  • すべてのデータベースユーザーにパスワードが割り当てられています
  • 最大:6時間37分51秒(216K q [9.000 qps]、10K接続、TX:2G、RX:174M)
  • 読み取り/書き込み:87%/ 13%
  • 合計バッファー:2.6Gグローバル+スレッドあたり4.6M(最大スレッド数400)
  • 可能な最大メモリ使用量:4.4G(インストールされているRAMの56%)
  • 遅いクエリ:1%(53/216K)(0.02%、以前は0.04%)
  • 使用可能な接続の最大使用率:2%(8/400)
  • キーバッファーサイズ/合計MyISAMインデックス:641.0M/255.0K
  • キーバッファーヒット率:99%(772Kキャッシュ/ 12読み取り)
  • クエリキャッシュが無効になっています
  • 一時テーブルを必要とするソート:1%(167一時ソート/ 24Kソート)6%から減少
  • ディスク上に作成された一時テーブル:36%(ディスク上の5K /合計15K)8%から減少
  • スレッドキャッシュヒット率:99%(8作成/ 10K接続)
  • テーブルキャッシュヒット率:9%(211オープン/ 2Kオープン)1%から増加
  • 使用されるオープンファイルの制限:0%(1/4K)
  • すぐに取得されたテーブルロック:100%(359K即時/ 359000ロック)
  • InnoDBデータサイズ/バッファープール:576.6M/2.0G
  • OPTIMIZE TABLEを実行してテーブルを最適化し、パフォーマンスを向上させる
  • MySQLは過去24時間以内に開始されました-推奨は不正確な場合があります
  • 調整するときは、tmp_table_size/max_heap_table_sizeを等しくします
  • LIMIT句を使用せずにSELECT DISTINCTクエリを減らす
  • Table_cacheを徐々に増やして、ファイル記述子の制限を回避します。
  • query_cache_size(> = 8M)
  • tmp_table_size(> 64M)
  • max_heap_table_size(> 16M)
  • table_cache(> 512)

クエリの例

これは今朝の午前8時47分に実行され、7.08秒かかりました。送信された行:10、検査された行:40。

MySQLクライアントで同じクエリを実行すると、0.06秒かかります。

SELECT  ProjectFile.id, ProjectFile.project_id, ProjectFile.document_type,
        ProjectFile.name, ProjectFile.project_file_type_id, ProjectFile.created,
        ProjectFileType.id, ProjectFileType.name, ProjectFileType.is_archived
    FROM  db.project_files AS ProjectFile
    LEFT JOIN  db.project_file_types AS ProjectFileType
        ON (ProjectFile.project_file_type_id = ProjectFileType.id)
    WHERE  ProjectFile.project_id = 19319
    ORDER BY  ProjectFileType.name ASC, ProjectFile.name ASC;

EXPLAIN出力:

*************************** 1. row *************************** id: 1 select_type: SIMPLE table: ProjectFile type: ref possible_keys: project_id key: project_id key_len: 5 ref: const rows: 10 Extra: Using where; Using temporary; Using filesort *************************** 2. row *************************** id: 1 select_type: SIMPLE table: ProjectFileType type: eq_ref possible_keys: PRIMARY key: PRIMARY key_len: 4 ref: db.ProjectFile.project_file_type_id rows: 1 Extra:

3
gazareth

それについてのコメントチューナーの出力

Data in InnoDB tables: 575M (Tables: 194)
Total fragmented tables: 194
Run OPTIMIZE TABLE to defragment tables for better performance

allInnoDBテーブルがどのようにフラグメント化されているかに注意してください。それが実装方法の性質です。煩わしいしないOPTIMIZE;それは実質的な利益を提供することはほとんどありません。

Joins performed without indexes: 7320

テーブルが小さい場合は関係ありません。重要なものは、log_queries_not_using_indexesがなくてもスローログに表示されます。 (その設定はオフのままにします。スローログが乱雑になるだけです。)

Temporary tables created on disk: 38% (31K on disk / 84K total)
Slow queries: 1% (476/982K)

最悪のものを見てみましょう。 EXPLAINSHOW CREATE TABLEを入力してください。 long_query_timeは2以下をお勧めします。

チューナーからの最後の5アイテムは増加しないでください。

チューナーのコメントの残りの部分は合理的です。

次のステップ

Pt-query-digestから出力を取得し、最初の2つに加えてEXPLAINSHOW CREATE TABLEを見てみましょう。

1
Rick James