ホームページ >データベース >mysql チュートリアル >例を使用して SQL を最適化する方法を説明します
最近ではハードウェアのコストが下がっていますが、ハードウェアをアップグレードしてシステムのパフォーマンスを向上させることも一般的な最適化方法です。リアルタイム性の高いシステムではやはりSQL面からの最適化が必要であり、今回はSQLの最適化方法を例に基づいて紹介します。
SQL に問題があるかどうかを判断する場合、次の 2 つの現象によって判断できます。
システム レベルの現象
CPU 消費量が深刻です
IO 待機が深刻です
ページの応答時間が長すぎますlong
タイムアウトやその他のエラーがアプリケーション ログに表示される
sar コマンドと top コマンドを使用できます。現在のシステムステータスを表示します。 Prometheus や Grafana などの監視ツールを通じてシステムのステータスを観察することもできます。
#実行プランの行とコストが非常に大きくなっています
問題 SQL の取得
データベースごとに取得方法が異なります。以下は、現在主流のデータベース用のスロー クエリ SQL 取得ツールです。
MySQL
スロークエリログ
テストツールloadrunner
Perconaのptqueryおよびその他のツール
AWR レポート
テスト ツール ロードランナーなど
v$、$session_wait などの関連内部ビュー
GRID CONTROL 監視ツール
## Dameng データベース
# Dameng パフォーマンス監視ツール (開発者)
v$、$session_wait などの関連内部ビュー
SQL 記述には次の一般的なスキルがあります:
• UNION
の代わりに UNION ALL を使用してください。最適化する場合SQL の実行 プロセッサは * を特定の列に変換する必要があり、各クエリはテーブルを返す必要があり、カバリング インデックスは使用できません。UNION ALL は UNION よりも実行効率が高くなります。UNION は実行時に重複排除する必要があります。UNION はデータを並べ替える必要があります
• select * の書き込みを避ける
• JOIN フィールドのインデックスを作成することをお勧めします一般に、JOIN フィールドには事前にインデックスが付けられます
• 複雑な SQL を避けるステートメント読みやすさを向上、クエリが遅くなる可能性を回避、複数の短いクエリに変換してビジネスエンドで処理可能
• データ列が複数回スキャンされる原因となる、rand() と同様の記述スタイルによる順序付けは避けてください。#• 1=1 の記述を避ける
RAND() によりデータ列が複数回スキャンされます。SQL 最適化
実行計画
SQL の最適化を完了する前に必ず実行計画を読んでください。実行計画には、効率が低い箇所と最適化が必要な箇所が示されます。 MYSQL を例として、実行計画がどのようなものかを見てみましょう。 (各データベースの実行計画は異なるため、自分で理解する必要があります)
説明 | |
---|---|
それぞれは独立して実行されます。操作識別子はオブジェクトを操作する順序を識別します。idの値が大きいほど最初に実行されます。同じ場合、実行順序は上から下です。 | |
クエリ内 各 select 句のタイプ | |
操作対象のオブジェクトの名前。通常はテーブル名ですが、他の形式です | |
一致するパーティション情報 (パーティション化されていないテーブルの値は NULL) | |
結合操作の種類 | |
使用される可能性のあるインデックス | |
オプティマイザによって実際に使用されるインデックス (最も重要な列) 最適な結合タイプから最悪の結合タイプまで、const、eq_reg、ref、range、index、および ALL です。 ALL が表示される場合は、現在の SQL に「悪臭」があることを意味します。 | |
オプティマイザによって選択されたインデックス キーの長さ (バイト単位) | |
はこの行の操作オブジェクトの参照オブジェクトを示します。参照オブジェクトは NULL | |
ではありません | Query 実行によってスキャンされたタプルの数 (innodb の場合、この値は推定値です)|
条件式のタプル数のパーセンテージフィルタリングされたテーブル | |
実行計画の重要な補足情報。この列に「ファイルソートを使用」、「一時を使用」という言葉が表示されている場合は注意してください。 SQL ステートメントを最適化する必要があります |
CREATE TABLE `a` ( `id` int(11) NOT NULLAUTO_INCREMENT, `seller_id` bigint(20) DEFAULT NULL, `seller_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, `gmt_create` varchar(30) DEFAULT NULL, PRIMARY KEY (`id`) ); CREATE TABLE `b` ( `id` int(11) NOT NULLAUTO_INCREMENT, `seller_name` varchar(100) DEFAULT NULL, `user_id` varchar(50) DEFAULT NULL, `user_name` varchar(100) DEFAULT NULL, `sales` bigint(20) DEFAULT NULL, `gmt_create` varchar(30) DEFAULT NULL, PRIMARY KEY (`id`) ); CREATE TABLE `c` ( `id` int(11) NOT NULLAUTO_INCREMENT, `user_id` varchar(50) DEFAULT NULL, `order_id` varchar(100) DEFAULT NULL, `state` bigint(20) DEFAULT NULL, `gmt_create` varchar(30) DEFAULT NULL, PRIMARY KEY (`id`) );現在時刻から10時間前後の現在のユーザーの注文状況をクエリし、昇順に並べ替える3つのテーブルが関連付けられています。具体的な SQL は次のとおりです
select a.seller_id, a.seller_name, b.user_name, c.state from a, b, c where a.seller_name = b.seller_name and b.user_id = c.user_id and c.user_id = 17 and a.gmt_create BETWEEN DATE_ADD(NOW(), INTERVAL – 600 MINUTE) AND DATE_ADD(NOW(), INTERVAL 600 MINUTE) order by a.gmt_create;View データ量 元の実行時間 元の実行計画
##初期の最適化アイデア
alter table b modify `user_id` int(10) DEFAULT NULL; alter table c modify `user_id` int(10) DEFAULT NULL; alter table c add index `idx_user_id`(`user_id`); alter table b add index `idx_user_id_sell_name`(`user_id`,`seller_name`); alter table a add index `idx_sellname_gmt_sellid`(`gmt_create`,`seller_name`,`seller_id`);
#警告情報の表示
最適化を続行します。テーブルの変更、「gmt_create」の日時の変更 DEFAULT NULL;
実行時間の表示
実行計画の表示
#概要
#SQL に関連するテーブル構造とインデックス情報を表示する
#最適化された実行時間と実行計画を表示します
mysql チュートリアル
」以上が例を使用して SQL を最適化する方法を説明しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。