かなり大きなMySQLデータベース(合計約35GB)があり、約900qpsを超えています。今のところパフォーマンスは大きな問題ではありませんが、プロジェクトは絶えず成長しており、事前に最適化について考え始めたいと思います。
最近、データベースのフォールトトレランスのために少なくとも3台のサーバーを追加できるInnoDB/NDBクラスターソリューションについて学びましたが、トラフィックの処理に複数のサーバーが関与しているため、全体的なパフォーマンスが向上するのでしょうか。
このプロジェクトは基本的にパブリック広告プラットフォームであり、ほとんどのトラフィックを受信する中央テーブルはわずかです。ユーザー、広告などです。単一の弱点を指摘することはできません。インフラストラクチャで最適化できるさまざまなことがたくさんあります(たとえば、ユーザー間に内部インスタントメッセージングがあります-MongoDBでどのように動作するかをテストする予定です。メッセージはこのデータベースアーキテクチャに適していると思います)
データベースサーバーのクエリ統計は次のとおりです。
トレードオフがあります。クラスタ内の複数の書き込み可能サーバーは、他のすべてのマシンにすべての書き込みを送信する必要があります。 読み取りは、クラスタリングやスレーブの恩恵を受けます。書き込みは、クラスタリングの恩恵をわずかしか受けません。 (シャーディングは、書き込みスケーリングの実際のソリューションです。)
1つのマスターに2つ以上のスレーブを追加することでさえ、書き込みsomeに役立ちます。これは、readsが少なくとも2つのスレーブに分散されているため、書き込みとの競合が少なくなっているためです。
急速に成長する場合:
ALTER
する必要がある場合は、完全なコピーに十分なスペースが必要になる場合があります。そして、あなたはディスクスペースを使い果たしたくありません。ALTERs
はますます長くかかります。現在InnoDBを使用している場合は、NDBに移行するための構造上の変更がいくつかあることがわかります。トランザクションモデルはまったく異なります(「結果整合性」)。アプリの種類によっては、問題になることもあれば、「レンガの壁」になることもあります。
MySQL/MariaDB内には、「InnoDB Cluster」(MySQL 8.0)とGalera Cluster(PXC、MariaDB)があります。それらはおそらく等しく「良い」です。
上記のすべてには、少なくとも3台のマシンが必要であり、できれば少なくとも3つのデータセンターに分散していることが望ましい。 (はい、データセンターはダウンする可能性があります。)
あなたがあなたのアプリについてより多くの詳細を提供するならば、おそらく私はもっと言うことができます。 SHOW CREATE TABLE
最大のテーブルについては、多くの洞察が得られる場合があります。
必要に応じて、指示に従ってください here ;トポロジやハードウェアを変更する前に、もう少しスケーリングできるようになるかもしれません。
もっと
ほとんどすべてのクエリはSELECTs
であるため、レプリケーションまたはクラスタリングトポロジはスケーリングに役立ちます。任意の数のスレーブが任意の量のスケーリングを提供できます。これらのスレーブは、単一のマスター(またはInnoDBクラスター)またはGaleraクラスターの3つのノードにハングアップできます。 NDBの動作は異なりますが、読み取り用に任意にスケーリングすることもできます。
したがって、あなたの質問に対する簡単な答えは「はい」です。どの解決策については、どちらの解決策があなたにとってより良いかは(まだ)言うことはありません。おそらく、言えることは「解決策を選んでそれを実行する」ことです。
変数とグローバルステータスのレビュー:
観察:
* Version: 10.3.15-MariaDB
* 16 GB of RAM
* Uptime = 64d 10:48:05
* You are not running on Windows.
* Running 64-bit version
* You appear to be running entirely (or mostly) InnoDB.
より重要な問題:
これはスタンドアロンのInnoDBデータベースであり、クラスター化されておらず、スレーブでもありませんか?
HDDまたはSSDのどちらを使用しているかを調べます。次に、以下の詳細のいくつかの項目を参照してください。
「クエリキャッシュ」を使用していますが、効率が悪く、システム全体の速度が低下している可能性があります。オフにするか、DEMAND
を使用して、どのSELECTs
にSQL_CACHE
を含めるかを慎重に選択することをお勧めします。
コミットはありませんか? autocommit = ONを使用していて、BEGINを使用したことがありますか?典型的なDMLクエリについて説明してください。 I/Oを減らすために、トランザクションを別の方法で使用することを提案する場合があります。
REPLACE
からINSERT ... ON DUPLICATE KEY UPDATE
に変更することを検討してください。
あなたの質問は、どのシステムを使用するかについてでした。ネットワーク帯域幅はあなたにとって大きな問題かもしれないことに注意してください(Bytes_sent = 7666357 /sec
);したがって、クエリの数と冗長性に対処することが役立つ場合があります(システムに依存しません)。
なぜこれほど多くのSHOW STATUS
呼び出しがあるのですか?
DELETEの全表スキャンがたくさんあります。特に大きなテーブルにいる場合は、それらとそれらを改善するための可能な方法について話し合いましょう。 ( http://mysql.rjweb.org/doc.php/deletebig )
詳細およびその他の所見:
( Table_open_cache_misses ) = 14,420,381 / 5568485 = 2.6 /sec
-table_open_cacheを増やす必要があるかもしれません(現在は2048)
( innodb_lru_scan_depth * innodb_page_cleaners ) = 1,024 * 4 = 4,096
- 1秒あたりのページクリーナーの作業量。 -「InnoDB:page_cleaner:1000msの意図したループがかかりました...」は、lru_scan_depthを下げることで修正できる可能性があります:1000/innodb_page_cleaners(現在は4)を検討してください。また、スワッピングを確認してください。
( innodb_page_cleaners / innodb_buffer_pool_instances ) = 4 / 6 = 0.667
--innodb_page_cleaners-innodb_page_cleaners(現在は4)をinnodb_buffer_pool_instances(現在は6)に設定することをお勧めします
( innodb_lru_scan_depth ) = 1,024
- "InnoDB:page_cleaner:1000msの意図されたループがかかりました..." lru_scan_depthを下げることで修正できます
( innodb_doublewrite ) = innodb_doublewrite = OFF
-追加のI/Oですが、クラッシュ時の安全性が向上します。 --FusionIO、Galera、Slaves、ZFSではOFFでOKです。
( Innodb_os_log_written / (Uptime / 3600) / innodb_log_files_in_group / innodb_log_file_size ) = 182,569,362,432 / (5568485 / 3600) / 2 / 2048M = 0.0275
-比率-(分を参照)
( Uptime / 60 * innodb_log_file_size / Innodb_os_log_written ) = 5,568,485 / 60 * 2048M / 182569362432 = 1,091
-InnoDBログローテーション間の分5.6.8以降、これは動的に変更できます。 my.cnfも必ず変更してください。 -(ローテーション間の60分の推奨はやや恣意的です。)innodb_log_file_size(現在は2147483648)を調整します。 (AWSでは変更できません。)
( innodb_flush_method ) = innodb_flush_method = fsync
-InnoDBがOSにブロックの書き込みを要求する方法。二重バッファリングを回避するために、O_DIRECTまたはO_ALL_DIRECT(Percona)を提案します。 (少なくともUnixの場合。)O_ALL_DIRECTに関する警告については、chrischandlerを参照してください。
( Innodb_row_lock_waits ) = 917,931 / 5568485 = 0.16 /sec
-行ロックの取得に遅延が発生する頻度。 -最適化できる複雑なクエリが原因である可能性があります。
( innodb_flush_neighbors ) = 1
-ブロックをディスクに書き込むときのマイナーな最適化。 --SSDドライブには0を使用します。 HDDの場合は1。
( innodb_io_capacity ) = 200
-ディスクで可能な1秒あたりのI/Oops。低速ドライブの場合は100。ドライブの回転には200。 SSDの場合は1000〜2000。 RAID係数を掛けます。
( sync_binlog ) = 0
-セキュリティを強化するために1を使用します。I/ O = 1のコストがかかると、多くの「クエリ終了」が発生する可能性があります。 = 0は、「不可能な位置でのbinlog」につながり、クラッシュ時にトランザクションを失う可能性がありますが、より高速です。
( innodb_print_all_deadlocks ) = innodb_print_all_deadlocks = OFF
-すべてのデッドロックをログに記録するかどうか。 -デッドロックに悩まされている場合は、これをオンにします。注意:デッドロックが多数ある場合、これによりディスクに大量の書き込みが発生する可能性があります。
( character_set_server ) = character_set_server = latin1
-文字セットの問題は、character_set_server(現在はlatin1)をutf8mb4に設定することで解決できる場合があります。これが将来のデフォルトです。
( local_infile ) = local_infile = ON
--local_infile(現在はオン)=オンは潜在的なセキュリティ問題です
( query_cache_size ) = 128M
-QCのサイズ-小さすぎる=あまり役に立たない。大きすぎる=オーバーヘッドが多すぎます。 0または50M以下を推奨します。
( Qcache_hits / Qcache_inserts ) = 1,259,699,944 / 2684144053 = 0.469
-ヒットと挿入の比率-高い方が良い-クエリキャッシュをオフにすることを検討してください。
( Qcache_hits / (Qcache_hits + Com_select) ) = 1,259,699,944 / (1259699944 + 3986160638) = 24.0%
-ヒット率-QCを使用したSELECT-クエリキャッシュをオフにすることを検討してください。
( Qcache_inserts - Qcache_queries_in_cache ) = (2684144053 - 46843) / 5568485 = 482 /sec
-無効化/秒。
( (query_cache_size - Qcache_free_memory) / Qcache_queries_in_cache / query_alloc_block_size ) = (128M - 59914960) / 46843 / 16384 = 0.0968
--query_alloc_block_size vsformula-query_alloc_block_sizeを調整します(現在は16384)
( Select_scan ) = 6,048,081 / 5568485 = 1.1 /sec
-全表スキャン-インデックスの追加/クエリの最適化(小さなテーブルでない限り)
( Com_stmt_prepare - Com_stmt_close ) = 4,138,804,898 - 4129522738 = 9.28e+6
-クローズされていない準備済みステートメントの数。 -準備されたステートメントを閉じる
( Com_replace ) = 28,182,079 / 5568485 = 5.1 /sec
-重複キーの更新時にINSERT ...に変更することを検討してください。
( binlog_format ) = binlog_format = MIXED
-STATEMENT/ROW/MIXED。 --ROWは5.7(10.3)によって優先されます
( slow_query_log ) = slow_query_log = OFF
-遅いクエリをログに記録するかどうか。 (5.1.12)
( long_query_time ) = 10
-「遅い」クエリを定義するためのカットオフ(秒)。 -提案2
( max_connect_errors ) = 999,999,999 = 1.0e+9
-ハッカーに対する小さな保護。 -おそらく200以下。
( Connections ) = 206,910,348 / 5568485 = 37 /sec
-接続-プーリングを使用しますか?
異常に小さい:
Com_show_tables = 0
Created_tmp_files = 0.12 /HR
Innodb_dblwr_pages_written = 0
Qcache_total_blocks * query_cache_min_res_unit / Qcache_queries_in_cache = 5,166
eq_range_index_dive_limit = 0
innodb_ft_min_token_size = 2
innodb_spin_wait_delay = 4
lock_wait_timeout = 86,400
query_cache_min_res_unit = 2,048
異常に大きい:
Access_denied_errors = 93,135
Acl_table_grants = 10
Bytes_sent = 7666357 /sec
Com_create_trigger = 0.0026 /HR
Com_create_user = 0.0013 /HR
Com_replace_select = 0.086 /HR
Com_reset = 1 /HR
Com_show_open_tables = 0.02 /HR
Com_show_status = 0.18 /sec
Com_stmt_close = 741 /sec
Com_stmt_execute = 743 /sec
Com_stmt_prepare = 743 /sec
Delete_scan = 43 /HR
Executed_triggers = 1.5 /sec
Feature_fulltext = 0.62 /sec
Handler_read_last = 0.83 /sec
Handler_read_next = 357845 /sec
Handler_read_prev = 27369 /sec
Innodb_buffer_pool_pages_misc * 16384 / innodb_buffer_pool_size = 16.2%
Innodb_row_lock_time_max = 61,943
Prepared_stmt_count = 3
Qcache_free_blocks = 24,238
Qcache_hits = 226 /sec
Qcache_inserts = 482 /sec
Qcache_total_blocks = 118,160
Select_range = 53 /sec
Sort_range = 47 /sec
Tc_log_page_size = 4,096
innodb_open_files = 10,000
max_relay_log_size = 1024MB
performance_schema_max_stage_classes = 160
異常な文字列:
aria_recover_options = BACKUP,QUICK
ft_min_Word_len = 2
innodb_fast_shutdown = 1
innodb_use_atomic_writes = ON
log_slow_admin_statements = ON
myisam_stats_method = NULLS_UNEQUAL
old_alter_table = DEFAULT
plugin_maturity = gamma