#この記事では、Explain を使用して SQL を分析する方法を紹介します。
実際、インターネット上には Explain の使用法を詳細に紹介する記事がたくさんあります。この記事では、例と原則を組み合わせて、理解を深めていただけるように努めています。信じてください。真剣に考えてください。読んだ後に特別な利益があります。 explain は「説明する」と訳されます。これは mysql では実行プランと呼ばれます。つまり、このコマンドを使用すると、オプティマイザによる分析後に mysql が SQL の実行をどのように決定するかを確認できます。 オプティマイザーについて言えば、もう 1 つ言わせてください。MySQL には強力なオプティマイザーが組み込まれています。オプティマイザーの主なタスクは、作成した SQL を最適化し、可能な限り低コストで実行することです。たとえば、スキャンする行を減らし、並べ替えを避けるなどです。 SQL ステートメントを実行するときに何を経験しましたか?前回の記事でオプティマイザについて紹介しました。 あなたは、通常どのようなときに Explain を使用するのかと疑問に思われるかもしれませんが、ほとんどの場合、クエリ効率が比較的遅い SQL は、Explain 分析を使用するために mysql のスロー クエリ ログから抽出されます。 , インデックスを追加し、追加したインデックスがヒットするかどうかを Explain を使用して分析するなど、ビジネス開発中にニーズが満たされる場合は、Explain を使用していずれかを選択する必要がある場合があります。 では、Explain を使用するにはどうすればよいでしょうか? それは非常に簡単で、以下に示すように SQL の前に Explain を追加するだけです。mysql> explain select * from t; +----+-------------+-------+------+---------------+------+---------+------+--------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+--------+-------+ | 1 | SIMPLE | t | ALL | NULL | NULL | NULL | NULL | 100332 | NULL | +----+-------------+-------+------+---------------+------+---------+------+--------+-------+ 1 row in set (0.04 sec)ご覧のとおり、explain は約 10 個のフィールドを返します。バージョンが異なると返されるフィールドは若干異なります。各フィールドは特定の意味を表します。この記事では各フィールドの詳細については説明しません。導入には多くの内容が含まれており、覚えるのは簡単ではないと思います。最初にいくつかの重要なフィールドを理解することをお勧めします。 フィールドの種類、キー、行、および追加の方が重要だと思います。これらのフィールドの意味をより深く理解できるように、具体的な例を使用します。 まず第一に、これらのフィールドの文字通りの意味を簡単に紹介する必要があります。 type は、MySQL がデータにアクセスする方法を表します。一般的なものには、フル テーブル スキャン (all)、インデックス トラバーサル (index)、間隔クエリ (範囲)、定数または同等のクエリ (ref、eq_ref)、主キーなどが含まれます。テーブル (システム) にレコードが 1 つだけある場合のクエリ (const)。以下は、最高から最低までの効率のランキングです。
system > const > eq_ref > ref > range > index > allkey は、クエリ プロセスで実際に使用されるインデックス名を表します。 rows は、クエリ プロセス中にスキャンする必要がある行数を表します。このデータは必ずしも正確ではなく、MySQL のサンプリング統計のデータです。 Extra は追加情報を表し、通常、インデックスが使用されているかどうか、並べ替えが必要かどうか、一時テーブルが使用されるかどうかなどを示します。 さて、サンプル分析を正式に始めましょう。 前回の記事で作成したストレージ エンジンを引き続き使用して、テスト テーブルを作成します。ここに 10 w 個のテスト データを挿入します。テーブルの構造は次のとおりです:
CREATE TABLE `t` ( `id` int(11) NOT NULL, `a` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB;次に、次のクエリ ステートメントでは、これに注意してください。テーブルには現在主キー インデックスが 1 つだけあり、通常のインデックスはまだ作成されていません。
mysql> alter table t add index a_index(a); Query OK, 0 rows affected (0.19 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> alter table t add index b_index(b); Query OK, 0 rows affected (0.20 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> show index from t; +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ | t | 0 | PRIMARY | 1 | id | A | 100332 | NULL | NULL | | BTREE | | | | t | 1 | a_index | 1 | a | A | 100332 | NULL | NULL | YES | BTREE | | | | t | 1 | b_index | 1 | b | A | 100332 | NULL | NULL | YES | BTREE | | | +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 3 rows in set (0.00 sec)タイプの値は ALL で、テーブル全体がスキャンされたことを示します。行フィールドには 100,332 のエントリが表示されることに注意してください。実際、データは合計 100,000 個しかないため、このフィールドはmysql の単なる推定値であり、必ずしも正確であるとは限りません。このフルテーブルスキャンの効率は非常に低いため、最適化する必要があります。 次に、フィールド a とフィールド b にそれぞれ通常のインデックスを追加し、インデックスを追加した後のいくつかの SQL ステートメントを確認します。
mysql> alter table t add index a_index(a); Query OK, 0 rows affected (0.19 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> alter table t add index b_index(b); Query OK, 0 rows affected (0.20 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> show index from t; +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ | t | 0 | PRIMARY | 1 | id | A | 100332 | NULL | NULL | | BTREE | | | | t | 1 | a_index | 1 | a | A | 100332 | NULL | NULL | YES | BTREE | | | | t | 1 | b_index | 1 | b | A | 100332 | NULL | NULL | YES | BTREE | | | +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 3 rows in set (0.00 sec)
mysql> explain select * from t where a > 1000; +----+-------------+-------+------+---------------+------+---------+------+--------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+--------+-------------+ | 1 | SIMPLE | t | ALL | a_index | NULL | NULL | NULL | 100332 | Using where | +----+-------------+-------+------+---------------+------+---------+------+--------+-------------+ 1 row in set (0.00 sec)上記の SQL は少しわかりにくいと思いますか? type は実際にフィールド a にインデックスが追加されたことを示しており、 possible_keys も a_index が利用可能であることを示していますが、キーは null を示しており、mysql が実際にインデックスを使用していないのですが、なぜですか? これは、* を選択した場合、b フィールドを見つけるために主キー インデックスに戻る必要があるためです。このプロセスはテーブル リターンと呼ばれます。このステートメントは、条件を満たす 90,000 個のデータをフィルターで除外します。つまり、これらの 9,000 個のデータはすべてテーブルを返す操作が必要であり、フル テーブル スキャンには 100,000 個のデータしか含まれていないため、MySQL オプティマイザの観点からは、直接のフル テーブルほど優れたものではありません。スキャンを実行すると、少なくともテーブルを返すプロセスが不要になります。 もちろん、これは、テーブルを返す操作がある限りインデックスにヒットしないという意味ではありません。インデックスを使用するかどうかの鍵は、mysql がどのクエリの方がコストが低いと考えるかによって決まります。上記の SQL の where 条件を少し変更してみましょう。
mysql> explain select * from t where a > 99000; +----+-------------+-------+-------+---------------+---------+---------+------+------+-----------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+-------+---------------+---------+---------+------+------+-----------------------+ | 1 | SIMPLE | t | range | a_index | a_index | 5 | NULL | 999 | Using index condition | +----+-------------+-------+-------+---------------+---------+---------+------+------+-----------------------+ 1 row in set (0.00 sec)今回のタイプ値は range で、キーは a_index です。これは、インデックスがヒットすることを意味します。この SQL 条件を満たすデータは 1000 個しかないため、これは適切な選択です。MySQLテーブルリターンはテーブル全体のスキャンよりもコストが低いので、mysql は実際には非常に賢い人です。 また、[Extra] フィールドの値が [インデックス条件を使用] であることもわかります。これは、インデックスは使用されていますが、テーブルを返す必要があることを意味します。次のステートメントを見てください。
mysql> explain select a from t where a > 99000; +----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+ | 1 | SIMPLE | t | range | a_index | a_index | 5 | NULL | 999 | Using where; Using index | +----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+ 1 row in set (0.00 sec)
这个 Extra 中的值为 Using where; Using index ,表示查询用到了索引,且要查询的字段在索引中就能拿到,不需要回表,显然这种效率比上面的要高,所以不要轻易写 select * ,只查询业务需要的字段即可,这样可以尽可能避免回表。
再来看一个需要排序的。
mysql> explain select a from t where a > 99000 order by b; +----+-------------+-------+-------+---------------+---------+---------+------+------+---------------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+-------+---------------+---------+---------+------+------+---------------------------------------+ | 1 | SIMPLE | t | range | a_index | a_index | 5 | NULL | 999 | Using index condition; Using filesort | +----+-------------+-------+-------+---------------+---------+---------+------+------+---------------------------------------+ 1 row in set (0.00 sec)
这个 Extra 中返回了一个 Using filesort,意味着需要排序,这种是需要重点优化的的,也就是说查到数据后,还需要 mysql 在内存中对其进行排序,你要知道索引本身就是有序的,所以一般来讲要尽量利用索引的有序性,比如像下面这样写。
mysql> explain select a from t where a > 99990 order by a; +----+-------------+-------+-------+------------------+---------+---------+------+------+--------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+-------+------------------+---------+---------+------+------+--------------------------+ | 1 | SIMPLE | t | range | a_index,ab_index | a_index | 5 | NULL | 10 | Using where; Using index | +----+-------------+-------+-------+------------------+---------+---------+------+------+--------------------------+ 1 row in set (0.00 sec)
我们再创建一个复合索引看看。
mysql> alter table t add index ab_index(a,b); Query OK, 0 rows affected (0.19 sec) Records: 0 Duplicates: 0 Warnings: 0
mysql> explain select * from t where a > 1000; +----+-------------+-------+-------+------------------+----------+---------+------+-------+--------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+-------+------------------+----------+---------+------+-------+--------------------------+ | 1 | SIMPLE | t | range | a_index,ab_index | ab_index | 5 | NULL | 50166 | Using where; Using index | +----+-------------+-------+-------+------------------+----------+---------+------+-------+--------------------------+ 1 row in set (0.00 sec)
这条 sql 刚刚在上面也有讲到过,在没有创建复合索引的时候,是走的全表扫描,现在其实是利用了覆盖索引,同样是免去了回表过程,即在 (ab_index) 索引上就能找出要查询的字段。
这篇文章通过几个实例介绍了如何使用 explain 分析一条 sql 的执行计划,也提到了一些常见的索引优化,事实上还有更多的可能性,你也可以自己去写一个 sql ,然后使用 explain 分析,看看有哪些是可以被优化的。
这篇文章我断断续续写了有三四天了,本来准备了更多的例子,但每次都是写了一部分,思路也打乱了,好了,有问题欢迎在下面留言交流,文章对你有帮助,点个赞表示鼓励支持。
更多MySQL相关技术文章,请访问MySQL教程栏目进行学习!
以上がSQLのパフォーマンスを分析する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

この記事では、パスワード管理を介した不正アクセスに対するMySQLサーバーのセキュリティ、リモートアクセスの制限、暗号化、および定期的な更新について説明します。また、セキュリティを強化するために、疑わしい活動の監視と検出をカバーしています。

この記事では、役割を使用してユーザー許可を効率的に管理し、役割の定義、許可の割り当て、動的調整の詳細を管理します。ロールベースのアクセス制御のベストプラクティスと、役割がユーザー管理ACRをどのように単純化するかを強調しています

この記事では、MySQLユーザーアカウントのパスワード、パスワードセキュリティのベストプラクティス、リモートパスワードの変更、パスワードポリシーのコンプライアンスの確保の方法について説明します。

記事では、MySQLの特権について説明します:グローバル、データベース、テーブル、列、ルーチン、およびプロキシユーザータイプ。それは、安全な管理のための許可、特権を取り消し、ベストプラクティスを説明しています。主張するリスクが強調されています。

この記事では、SQLでの助成金ステートメントの使用を説明して、特定のデータベースオブジェクトのユーザーや役割の選択、挿入、更新などのさまざまな特権を割り当てます。また、Revoke Statementでの取り消し特権をカバーし、Privilegを付与します

記事では、MySQLユーザーの作成を作成し、ユーザーステートメントの作成、特権の割り当て、パスワードの設定、ユーザー名の選択について説明します。

記事では、安全なマルチユーザーデータベース管理のためのSQLコマンドとベストプラクティスに焦点を当てた、ストアドプロシージャと機能に関する実行権限を付与することについて説明します。

この記事では、SQL Serverに焦点を当てた、他のストアドプロシージャまたは関数内からのストアドプロシージャの呼び出しについて説明します。構文、モジュール性とセキュリティなどの利点、ネストされた手順のエラー処理、設計上の考慮事項をカバーします。


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

SAP NetWeaver Server Adapter for Eclipse
Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。

DVWA
Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、

SublimeText3 英語版
推奨: Win バージョン、コードプロンプトをサポート!

メモ帳++7.3.1
使いやすく無料のコードエディター

AtomエディタMac版ダウンロード
最も人気のあるオープンソースエディター
