MySQL パフォーマンス最適化の 5 つの側面
1. データベース接続構成の最適化
1. サーバーが行う必要があるのは、できるだけ多くのクライアント接続を受け入れることです。おそらく、エラー 1040: 接続が多すぎますか? サーバー側の接続数が足りないだけです。
2. クライアントができることは、サーバーとの接続を確立する回数を最小限に抑えることです。すでに確立されている接続が使用できる場合はそれを使用します。SQL ステートメントを実行するたびに新しい接続を作成しないでください。両方のリソースサーバーとクライアントに負荷がかかります。
1. サーバー接続の最大数の最適化された構成
サーバーが行う必要があるのは、できるだけ多くのクライアント接続を受け入れることです。エラー 1040: 接続が多すぎますか? というエラーが発生したことがあるかもしれません。サーバー側の接続数が足りないだけです。
クライアントができることは、サーバーとの接続を確立する回数を最小限に抑えることです。既存の接続が使用できる場合はそれを使用します。SQL ステートメントが実行されるたびに新しい接続を作成しないでください。両方のサーバーのリソースそしてクライアントは圧倒されるでしょう。
解決策は、接続プールを使用して接続を再利用することです。
(1)方法
1: 使用可能な接続数を増やし、環境変数 max_connections を変更します。デフォルトでは、サーバー上の最大接続数は 151 です
mysql> show variables like ' max_connections';
± ----------±------+
| 変数名 | 値 |
±-------------- ±--- ---+
| max_connections | 151 |
±-----±------+
セット内の 1 行 (0.01 秒)
set GLOBAL max_connections=1000; #最大接続数を 1000 に変更します
(2) 方法 2 /etc/my.cnf #データベース設定ファイルに
設定 max_connections=1500 を追加#最大接続数を 1500 に変更し、変更後にデータベースを再起動します。
2. 非アクティブな接続を解放します
非アクティブな接続を適時に解放します。システムのデフォルトのクライアント タイムアウトは 28800 秒 (8 時間) です。この値をより小さく調整できます
。mysql> show variables like 'wait_timeout';
±---------- --- -±-----+
| 変数名 | 値 |
±--------------±------+
| wait_timeout | 28800 |
±---- --- -------±------+
1 行 (0.01 秒)
構成ファイル
/etc/my.cnfを変更します。
interactive_timeout=18800
wait_timeout=18800
データベースを再起動します
2. アーキテクチャの最適化
1. キャッシュを使用する
(1) 特に有効なデータではない場合(日報など刻一刻と変化しないデータ)、この種のデータをキャッシュシステムに置き、データのキャッシュ有効期間内に直接データを取得することもできます。キャッシュ システム: データベースからデータを取得すると、データベースへの負荷が軽減され、クエリの効率が向上します。
2. 読み書きの分離
(1) 複数のデータベースサーバーを同時に使用することができ、そのうちの 1 台をマスターノードと呼ばれるチームリーダーに設定し、他のノードをスレーブと呼ばれるチームメンバーに設定します。ユーザーはマスター ノードにのみデータを書き込み、読み取りリクエストはさまざまなスレーブ ノードに分散されます。この解決策は、読み取りと書き込みの分離と呼ばれます。
(2) クラスタを使用すると、複数のノード間でデータの整合性を維持するためのマスター/スレーブ レプリケーションという問題が避けられません。
Binlog は、MySQL のマスター/スレーブ レプリケーション機能を実装するコア コンポーネントです。
①. スレーブ側 IO スレッドがマスター側 binlog (バイナリログ) スレッドにリクエストを送信
②. マスター側 binlog ダンプ スレッドがバイナリログ情報 (ファイル名と位置情報) を取得してスレーブに送信-側IOスレッド
③.スレーブ側IOスレッドで取得した内容 スレーブ側リレーログ(リレーログ)に順番に書き込み、マスター側のbin-logファイル名と場所をhttp:/に記録します。 /master.info ④.
スレーブ側の SQL スレッドは、リレーログの内容が更新されたことを検出すると、リレーログの更新内容を解析し、マスターデータとの整合性をとるためにこれらの操作を実行します。
3. サブライブラリとサブテーブル
データベースとテーブルのシャーディングの概要: 概要: 水平シャーディングは主にストレージのボトルネックを解決するためのものであり、垂直シャーディングは主に同時実行の圧力を軽減するためのものです。
(1) 垂直シャーディング。
シャーディング データベースおよびシャーディング テーブルにおけるノードの意味は比較的広く、データベースがノードとして使用される場合はシャーディング データベースであり、単一のテーブルがノードとして使用される場合はシャーディング テーブルです。 。
サブライブラリとテーブルのサブディビジョンは、垂直サブデータベース、垂直サブテーブル、水平サブデータベース、水平サブテーブルに分かれています。
単一のデータベースを基に、ビジネス ロジックに応じて複数の垂直方向に分割し、異なるデータベースに分割したものが垂直サブデータベースです。
(2) 表の垂直分割
表の垂直分割とは、1 つの表を垂直に 1 つ(または複数の切り取り)で切り、表の複数の単語をいくつかの小さな表に分割することであり、業務に応じて実施する必要があります。 , 通常、頻繁に使用されるフィールド (ホット フィールド) はテーブルに分割され、頻繁に使用されないフィールドまたはすぐには使用されないフィールド (コールド フィールド) はクエリの速度を向上させるためにテーブルに分割されます。
(3) テーブルの水平分割:
単一のテーブルのデータを一定のルール (専門用語ではシャーディング ルールと呼びます) に従って複数のデータ テーブルに保存し、データ テーブルに 1 つのナイフ (または複数のナイフ) を水平に適用します。これが水平テーブル分割です。 。
(4) 水平サブデータベース
水平サブデータベースは 1 つのデータベースを水平に分割するものであり、多くの場合、テーブルの水平分割が伴います。
4. メッセージキュー
通常、ユーザーのリクエストはデータベースに直接アクセスしますが、同時にオンライン ユーザーの数が非常に多い場合、データベースが超過する可能性が非常に高くなります (有名人の浮気や交際発表時の Weibo の状況を参照してください)。
この場合、メッセージ キューを使用することでデータベースへの負荷を軽減できます。同時にユーザーからのリクエストがいくつあっても、リクエストはまずメッセージ キューに格納され、その後システムがメッセージからのリクエストを消費します。整然と列に並びます。
3. SQLの分析と最適化
1. クエリが遅い
遅いクエリとは、実行が非常に遅いクエリのことで、MySQL にどのような遅いクエリがあるのかを知ることによってのみ、対象を絞った最適化を実行できます。
スロー クエリ ログをオンにするとパフォーマンスが低下するため、MySQL はデフォルトでスロー クエリ ログ機能をオフにします。現在のスロー クエリ ステータスを表示するには、次のコマンドを使用します。
'slow_query%' のような変数を表示;
mysql> 'slow_query%' のような変数を表示;
±----------------------±---------- ------------------------+
| 変数名 | 値 |
±------------ ---- ----± ----------------------------------------------------+
|slow_query_log | オフ |
|slow_query_log_file | /var/lib/mysql/9e74f9251f6c-slow.log |
±----------------------±------ ------- ------------+
セット内の 2 行 (0.00 秒)
throw_query_log は、スロー クエリ ログが現在有効かどうかを示します。また、slow_query_log_file は、スロー クエリ ログの保存場所を示します。
上記の 2 つの変数に加えて、「遅い」インジケーターが何か、つまり、クエリの実行にどのくらい時間がかかると遅いクエリとみなされるかを決定する必要もあります。デフォルトは 10 秒です。0 に変更した場合は、 、すべての SQL では、「%long_query% が記録されます
。」のような変数が表示されます。
mysql> '%long_query%' のような変数を表示します。
±----------------±----------+
| 変数名 | 値 |
±----------------±----------+
| 長いクエリ時間 | 10.000000 |
±----------------±----------+
1 行 (0.00 秒)
2. スロークエリログを開く
(1) 方法 1: 設定ファイル my.cnf を変更する
この変更は、システムの再起動後も有効です。
#スロークエリログを有効にするかどうか
throw_query_log=ON
long_query_time=2
throw_query_log_file=/var/lib/mysql/slow.log
(2) 方法 2: パラメータを動的に変更する (再起動後は無効)
mysql> set @@global.slow_query_log=1;
Query OK, 0 rows according to (0.06 sec)
mysql> set @@global.long_query_time=2;
Query OK, 0影響を受ける行 (0.00 秒)
3. スロークエリログ分析
MySQL はスロー ログ ファイルを保存するだけでなく、スロー ログ クエリ ツール mysqldumpslow も提供します。このツールをデモンストレーションするために、まずスロー クエリを作成します: mysql> SELECT sleep(5); スロー クエリの数を表示するlog
records
:
SHOW GLOBAL STATUS LIKE '%Slow_queries%';
次に、最も時間がかかる遅いクエリをクエリします。
mysqldumpslow -st -t 1 -g 'select' /var/lib/mysql/9e74f9251f6c-slow.log
/var/lib/mysql/9e74f9251f6c-slow.log から mysql スロー クエリ ログを読み取ります
回数: 1 時間 = 10.00 秒 (10 秒) ) Lock=0.00s (0s) Rows=1.0 (1), root[root]@localhost
SELECT sleep(N)
このうち
、Count: このSQLが実行された回数を示し、
Time: 実行時間を示します。括弧内の時間は
Locks: ロック時間を示し、括弧内は累積時間です
Rows: 返されたレコード数を示し、括弧内は累積数です。
cat /var/lib/mysql/data/slow.log
SHOW プロファイル SQL クエリ SQL の消費時間を表示
ライフサイクル全体の消費時間は、
Query_ID から取得できます 接続 - サービスまでの 4 層構造の完全なライフサイクル- エンジン - ストレージ サイクル タイム
SHOW プロファイル CPU、クエリ 4 のブロック IO;
利用可能なパラメータ タイプ:
ALL # すべてのオーバーヘッド情報を表示
BLOCK IO # ブロック IO 関連のオーバーヘッドを表示
CONTEXT SWITCHES # コンテキスト スイッチング関連のオーバーヘッド
CPU # CPU 関連のオーバーヘッド情報を表示
IPC #送受信関連のオーバーヘッド情報を表示
MEMORY # メモリ関連のオーバーヘッド情報を表示
PAGE FAULTS # ページフォールト関連のオーバーヘッド情報を表示
SOURCE # Source_function、Source_file、Source_line に関連したオーバーヘッド情報を表示
SWAPS # スワップ数に関連したオーバーヘッド情報を表示
4. 実行中のスレッドを表示する
show full processlist を実行すると、MySQL で実行中のすべてのスレッドを表示し、そのステータスと実行時間を表示し、実行時間の長いサイトを見つけて、それらを直接強制終了できます。
このうち、
Id: スレッドの一意の識別子。Id を使用して指定したスレッドを強制終了できます。
ユーザー: このスレッドを開始したユーザー。通常のアカウントは自分のスレッドのみを表示できます。
ホスト: 接続を開始した IP とポート.
db: スレッドによって操作されるデータベース
Command: スレッドのコマンド
Time: 操作時間 (秒単位)
State: スレッドのステータス
Info: SQL ステートメントの最初の 100 文字
5. サーバーの稼働状況を確認する
show status コマンドを直接使用して 300 を超えるレコードを取得するのは大変なことなので、オンデマンドでステータス情報を「表示」できるようにしたいと考えています。この時点で、show status ステートメントの後に対応する like 句を追加できます。たとえば、MySQL の起動後の現在の実行時間を表示したい場合は、次のステートメントを実行できます。
SHOW STATUS コマンドを使用して、サーバーのステータス情報を表示します。
具体的なコマンドは次のとおりです。 global の追加はグローバル変数を表します。
1) select ステートメントの実行数を確認する:
show [global] status like 'com_select';
2) insert ステートメントの実行数を確認する:
show [global] status like 'com_insert';
3) の実行数を確認するupdate ステートメント:
show [global] ] status like 'com_update';
4) delete ステートメントの実行数を表示:
show [global] status like 'com_delete';
5) MySQL に接続しようとしている接続数を表示します (接続が成功したかどうか):
'connections' などのステータスを表示;
6) スレッド キャッシュ内のスレッド数を表示:
'threads_cached' などのステータスを表示;
7) 現在開いている接続の数を表示:
'threads_connected' などのステータスを表示;
8 ) 接続を処理するために作成されたスレッドの数を表示します。
show status like 'threads_created';
9) アクティブ化された (非スリープ) スレッドの数を表示します:
show status like 'threads_running';
10) すぐに取得されたテーブル ロックの数を表示します:
show status like 'table_locks_immediate';
11) 表示できませんすぐに取得されたテーブル ロックの数。値が高く、パフォーマンスに問題がある場合は、最初にクエリを最適化してからテーブルを分割するか、レプリケーションを使用する必要があります:
show status like 'table_locks_waited';
12) throw_launch_time 秒より長く作成されたスレッドの数を表示します:
show status like 'slow_launch_threads' ;
13) クエリ時間が long_query_time 秒を超えたクエリの数を確認する:
show status like 'slow_queries';
14) この起動後の MySQL の実行時間を確認する (単位: 秒):
show status like 'uptime' ;
15) 前のクエリのコストを確認します。
show status like 'last_query_cost'
16) クエリ キャッシュ情報を表示します
show status like 'qcache%';
6. ストレージ エンジンの実行状態を確認します
(1)。SHOW ENGINE は、トランザクションが保持するテーブル ロックと行ロック情報、トランザクションのロック待機状態、スレッド セマフォの待機状態など、ストレージ エンジンの現在の実行情報を表示するために使用されます。ファイル IO リクエスト、バッファ プール統計およびその他のデータ。
(2) InnoDB バージョンをクエリ
show variables like 'innodb_version'\G;
または select * from information_schema.plugins;
mysql> show variables like 'innodb_version'\G;
*************** ************ 1. 行 ****************************
変数名: innodb_version
値: 5.7.31 -34
セット内の 1 行 (0.01 秒)
クエリ InnoDB ステータス
次のクエリからわかるように、これは最後の 47 秒で計算された 1 秒あたりの平均数です。つまり、パラメータは各クエリ中に動的に変化します。
mysql> エンジンの
innodb ステータスを表示\G;
** 1. 行 ***************
タイプ: InnoDB
名前:
ステータス:
===============
2022-06-27 09:33:40 0x
7fa1c8a5f700 INNODB
モニター出力
===============
過去
47 秒から計算された1 秒あたりの平均
BACKGROUND THREAD
(バックグラウンド スレッド)
srv_master_thread ループ数
: 13285067 srv_active、0
srv_shutdown、1060666
6 srv_idle
srv_master_thread ログの
フラッシュと書き込み: 238917
33
#####上記のクエリに示されているように、srv
master_thread ループ数は
マスター スレッド ループの数であり
、
状態は(アクティブ、
シャットダウン、アイドル) 実行であり、
アクティブ数の増加は
データ変更に関連しており、クエリとは何の関係も
ありません。 srv_idle
.
active と idle の値を比較することで、
システム全体の負荷を取得し、
active の値が大きいほど
サービスが混雑していることを示します。
#####srv_master_ thread log は、マスタースレッドが REDO ログ (REDOログ) をディスクに書き込む
回数です。
セマフォ (セマフォ
)
OS 待機配列情報:
予約数 57836
764 #####OS 待機配列
情報: 期待数 (
InnoDB 割り当てスロット クォータ)
OS 待機配列情報:
シグナル数 269276481
#####OS 待機
配列情報: シグナル数 (スレッド
アレイを通じて信号周波数を取得)
RW 共有スピン 0、
ラウンド 171890114、OS
待機数 34656067 ###
##RW 共有ロック数、
ポーリング時間、待機時間
RW-excl スピン 0、ラウンド
1245774156、OS 待機数
18379769 ### ##
RW の排他ロック数、
ポーリング時間、待機時間
RW-sx スピン 80621、
ラウンド 1707842、OS
待機 34552 #
####RW の sx (意図排他
ロック) カウント、ポーリング
1890114.00
待機ごとのスピン ラウンド: 17
-shared、
1245774156.00 RW-
excl, 21.18 RW-sx ##
###待機ごとの各スピン ラウンド
の表示: 各オペレーティング
システムはミューテックス
スピンロック ラウンドを待機します
...
上記のステートメントは、innodb ストレージ エンジンの現在の操作に関するさまざまな情報を表示できます。 MySQL がそのような監視ツールを提供していることを知っていれば、必要に応じて詳細にクエリを実行できます。
- BACKGROUND THREAD (バックグラウンド スレッド)
- セマフォ (セマフォ)
- 最後に検出されたデッドロック
- 取引
- FILE I/O(文件IO)
- INSERT BUFFER AND ADAPTIVE HASH INDEX (挿入バッファと適応ハッシュ インデックス)
- ログ
- BUFFER POOL AND MEMORY (バッファプールとメモリ)
- 行の操作
7. EXPLAN 実行計画
遅いクエリのログを通じて、どの SQL ステートメントの実行が遅いのかを知ることができますが、なぜ遅いのでしょうか? どこが遅いのでしょうか?
MySQL には、実行プラン クエリ コマンド EXPLAIN が用意されています。このコマンドを通じて、SQL 実行プランを表示できます。EXPLAIN は、
MySQL 5.6.3 以降の UPDATE、DELETE、および INSERT ステートメントでも分析できますが、通常は引き続き SELECT クエリに使用されます。
SQL の最適化とは、SQL 自体の構文には問題はないが、同じ目的を達成するためにより良い記述方法があることを意味します。例えば:
使用小表驱动大表;用join改写子查询;or改成union
连接查询中,尽量减少驱动表的扇出(记录数),访问被驱动表的成本要尽量低,尽量在被驱动表的连接列上建立索引,降低访问成本;被驱动表的连接列最好是该表的主键或者是唯一二级索引列,这样被驱动表的成本会降到更低
大偏移量的limit,先过滤再排序
最後のステートメントの簡単な例を見てみましょう。次の 2 つのステートメントは同じ目的を達成できますが、2 番目のステートメントの実行効率は最初のステートメントよりもはるかに高くなります (ストレージ エンジンは InnoDB を使用します)。それを感じてみましょう:
– 1. 大きなオフセットを使用したクエリ
mysql> SELECT * FROM user_innodb LIMIT 9000000,10;
空のセット (8.18 秒)
– 2. 最初に ID をフィルタリングします (ID はインデックスを使用しているため)。次に、limit
mysql> SELECT * FROM user_innodb WHERE id > 9000000 LIMIT 10;
空のセット (0.02 秒)
インデックスの最適化
遅いクエリに対して適切なインデックスを作成することは非常に一般的で非常に効果的な方法ですが、インデックスが効率的に使用されるかどうかは別のトピックです。
4. ストレージエンジンとテーブル構造の最適化
1.ストレージエンジンの選択
通常の状況では、MySQL のデフォルトのストレージ エンジンである InnoDB を選択しますが、データベースのパフォーマンス要件が継続的に向上している場合、ストレージ エンジンの選択も重要な影響要因になります。
多くのクエリ操作と挿入操作を行うビジネス テーブルの場合は MyISAM を使用することをお勧めします。
一時テーブルの場合は Memory を使用します。
大規模な同時実行と多くの更新を行うビジネスの場合は InnoDB を選択します。
何を選択すればよいかわからない場合は、デフォルトのままにしてください。
2. フィールドの最適化
フィールド最適化の最後の原則は、データを正しく保存できる最小のデータ型を使用することです。
整数型: 異なる記憶域タイプには異なる最大記憶範囲があり、当然異なる記憶領域を占有します
。文字型: データの長さがわからない場合は、フィールドの場合は、Choose varchar にする必要がありますが、varchar には、フィールドが現在占有している長さを記録するために追加のスペースが必要です。そのため、フィールドの長さが固定されている場合は、メモリ スペースを大幅に節約できる char を使用してください。
非 null: 非 null フィールドを NOT NULL に設定してデフォルト値を提供するか、NULL の代わりに特別な値を使用してください。
外部キー、トリガー、ビュー関数は使用しないでください。
画像、オーディオ、およびビデオのストレージ: 使用しないでください。大きなファイルを直接保存する; 大きなファイルのアドレスにアクセスする
大規模なフィールド分割とデータの冗長性
5. ビジネスの最適化
1. ビジネスの最適化は、もはや MySQL チューニングの手段ではありませんが、ビジネスの最適化は、データベース アクセスのプレッシャーを非常に効果的に軽減できます。この点における典型的な例は、淘宝網です。 1. 以前は、買い物はダブル 11 の夜に始まりました。モデル
、近年、ダブル 11 のプレセール期間は半月以上前から開始されるなど、ますます長期化しており、さまざまな入金紅包モデルが際限なく登場しており、この方法はプレセール転用と呼ばれています。これにより、顧客のサービス要求をそらすことができ、まとめて注文するためにダブルイレブンの早朝まで待つ必要がなくなります。 2. アリペイは、考慮事項の一部ではあるものの、ダブルイレブン中に銀行カード
支払いの代わりに花北支払いを使用することを強く推奨します。ソフトウェアの粘着性を向上させるためですが、その一方で、余額宝が実際に使用しているアリババの内部サーバーを使用するとアクセス速度が速いのに対し、銀行カードを使用すると銀行インターフェイスを呼び出す必要があり、比較するとはるかに遅くなります。