MySQLがフルテーブルスキャンを実行するいくつかの状況

MySQLがフルテーブルスキャンを実行するいくつかの状況

過去 2 日間で、完全なテーブル スキャンを引き起こす可能性のある 2 種類の SQL を確認しました。落とし穴を避けるために、次の 2 つの例をご覧ください。

ケース1:

強制型変換の場合、インデックスは使用されず、テーブル全体のスキャンが実行されます。

以下にいくつか例を挙げます。

まずテーブルを作成します

 テーブル「test」を作成します(
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `age` int(11) デフォルト NULL,
  `score` varchar(20) NOT NULL DEFAULT '',
  主キー (`id`)、
  キー `idx_score` (`score`)
) エンジン=InnoDB AUTO_INCREMENT=12 デフォルト文字セット=utf8

このテーブルには 3 つのフィールドがあり、そのうち 2 つは int 型で 1 つは varchar 型であることがわかります。 varchar 型フィールドのスコアはインデックスであり、id は主キーです。

次に、このテーブルにデータを挿入します。データ挿入後のテーブルは次のようになります。

mysql:yeyztest 21:43:12>>テストから*を選択します。
+----+------+-------+
| ID | 年齢 | スコア |
+----+------+-------+
| 1 | 1 | 5 |
| 2 | 2 | 10 |
| 5 | 5 | 25 |
| 8 | 8 | 40 |
| 9 | 2 | 45 |
| 10 | 5 | 50 |
| 11 | 8 | 55 |
+----+------+-------+
セット内の行数は 7 です (0.00 秒)

この時点で、explain ステートメントを使用して、次の 2 つの SQL ステートメントの実行を表示します。

スコアが '10' であるテストから * を選択します。

スコア =10 のテストから * を選択します。

結果は次のとおりです。

mysql:yeyztest 21:42:29>>スコア='10'; でテストから * を選択します。
+----+-------------+---------+-----------+--------+---------------+------------+-------+-------+------+------+------+------+
| id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 |
+----+-------------+---------+-----------+--------+---------------+------------+-------+-------+------+------+------+------+
| 1 | SIMPLE | テスト | NULL | ref | idx_score | idx_score | 62 | const | 1 | 100.00 | NULL |
+----+-------------+---------+-----------+--------+---------------+------------+-------+-------+------+------+------+------+
セットに 1 行、警告 1 件 (0.00 秒)

mysql:yeyztest 21:43:06>>スコア=10のテストからselect *を説明します。
  +----+-------------+--------+-----------+--------+---------------+-------+--------+----------+-----------+-------------+
| id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 |
+----+-------------+--------+-----------+--------+---------------+-------+--------+----------+-----------+-------------+
| 1 | SIMPLE | テスト | NULL | ALL | idx_score | NULL | NULL | NULL | 7 | 14.29 | where の使用 |
+----+-------------+--------+-----------+--------+---------------+-------+--------+----------+-----------+-------------+
セットに 1 行、警告 3 件 (0.00 秒)

varchar 型の値を使用すると、結果でスキャンされる行数は 1 であり、整数値 10 を使用すると、スキャンされる行数は 7 になることがわかります。これは、強制的な型変換が発生すると、インデックスが無効になることを示しています。

ケース2:

逆クエリではインデックスを使用できないため、テーブル全体のスキャンが行われます。

主キーが score であるテーブル test1 を作成し、6 つのレコードを挿入します。

テーブル「test1」を作成します(
  `score` varchar(20) NULLでないデフォルト '' ,
  主キー (`score`)
) エンジン=InnoDB デフォルト文字セット=utf8

mysql:yeyztest 22:09:37>>test1から*を選択します。
+-------+
| スコア |
+-------+
| 111 |
| 222 |
| 333 |
| 444 |
| 555 |
| 666 |
+-------+
セット内の 6 行 (0.00 秒)

逆引き検索を使用する場合、インデックスは使用されません。次の 2 つの SQL ステートメントを見てみましょう。

select * from test1 where score='111'; を説明します。

select * from test1 where score!='111'; を説明します。
mysql:yeyztest 22:13:01>>スコア='111'; で test1 から select * を実行します。
+----+-------------+---------+-----------+---------+---------------+---------+--------+----------+-----------+-------------+
| id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 |
+----+-------------+---------+-----------+---------+---------------+---------+--------+----------+-----------+-------------+
| 1 | SIMPLE | test1 | NULL | const | PRIMARY | PRIMARY | 62 | const | 1 | 100.00 | インデックスを使用 |
+----+-------------+---------+-----------+---------+---------------+---------+--------+----------+-----------+-------------+
セットに 1 行、警告 1 件 (0.00 秒)

mysql:yeyztest 22:13:08>>explain select * from test1 where score!='111';
+----+-------------+--------+-----------+---------+---------------+---------+-------+-------+----------+----------------------------+
| id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 |
+----+-------------+--------+-----------+---------+---------------+---------+-------+-------+----------+----------------------------+
| 1 | SIMPLE | test1 | NULL | index | PRIMARY | PRIMARY | 62 | NULL | 6 | 100.00 | where の使用; index の使用 |
+----+-------------+--------+-----------+---------+---------------+---------+-------+-------+----------+----------------------------+
セットに 1 行、警告 1 件 (0.00 秒)

見ればわかります、使ってみてください! = 条件として使用する場合、スキャンされる行数はテーブル内の行の合計数になります。したがって、インデックスを使用する場合は、逆一致ルールは使用できません。

ケース3:

特定の条件または値条件により、テーブル全体のスキャンが実行される場合があります。

まずテーブルを作成し、データを挿入します。

テーブル「test4」を作成します(
  `id` int(11) デフォルト NULL,
  `name` varchar(20) デフォルト NULL,
  キー `idx_id` (`id`)
) エンジン=InnoDB デフォルト文字セット=utf8
セット内の 1 行 (0.00 秒)

mysql--dba_admin@127.0.0.1:yeyztest 22:23:44>>test4 から * を選択します。
+------+------+
| ID | 名前 |
+------+------+
| 1 | ああ |
| 2 | bbb |
| 3 | ccc |
| 4 | うんざり |
| NULL | ええと |
+------+------+
セット内の行数は 5 です (0.00 秒)

テーブル test4 には 2 つのフィールドがあります。id フィールドはインデックスで、name フィールドは varchar 型です。次の 3 つのステートメントでスキャンされた行の数を見てみましょう。

select * from test4 where id=1; を説明します。

id が null である test4 から * を選択します。

select * from test4 where id=1 or id is null; を説明します。
mysql:yeyztest 22:24:12>>idがnullの場合にtest4から*を選択することを説明します。
+----+-------------+--------+-----------+--------+---------------+---------+-------+--------+---------+------------------------+
| id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 |
+----+-------------+--------+-----------+--------+---------------+---------+-------+--------+---------+------------------------+
| 1 | SIMPLE | test4 | NULL | ref | idx_id | idx_id | 5 | const | 1 | 100.00 | インデックス条件を使用 |
+----+-------------+--------+-----------+--------+---------------+---------+-------+--------+---------+------------------------+
セットに 1 行、警告 1 件 (0.00 秒)

mysql:yeyztest 22:24:17>>select * from test4 where id=1; の説明
                      +----+-------------+--------+-----------+--------+---------------+---------+-------+-------+------+------+------+
| id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 |
+----+-------------+--------+-----------+--------+---------------+---------+-------+-------+------+------+------+
| 1 | SIMPLE | test4 | NULL | ref | idx_id | idx_id | 5 | const | 1 | 100.00 | NULL |
+----+-------------+--------+-----------+--------+---------------+---------+-------+-------+------+------+------+
セットに 1 行、警告 1 件 (0.00 秒)

mysql:yeyztest 22:24:28>>explain select * from test4 where id=1 or id is null;
+----+-------------+--------+-----------+--------+---------------+-------+--------+----------+-----------+-------------+
| id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 |
+----+-------------+--------+-----------+--------+---------------+-------+--------+----------+-----------+-------------+
| 1 | SIMPLE | test4 | NULL | ALL | idx_id | NULL | NULL | NULL | 5 | 40.00 | where の使用 |
+----+-------------+--------+-----------+--------+---------------+-------+--------+----------+-----------+-------------+
セットに 1 行、警告 1 件 (0.00 秒)

id=1 と id is null のみを使用すると、レコードの 1 行のみがスキャンされますが、 または を使用して 2 つを接続すると、インデックスを使用せずにテーブル全体がスキャンされることがわかります。

簡単にまとめると:

1. 強制型変換の場合、インデックスは使用されず、テーブル全体のスキャンが実行されます。

2. 逆クエリではインデックスを使用できないため、テーブル全体がスキャンされます。

3. 一部の条件または値条件により、テーブル全体のスキャンが実行される場合があります。

上記は、MySQL がフル テーブル スキャンを実行するいくつかの状況の詳細です。MySQL フル テーブル スキャンの詳細については、123WORDPRESS.COM の他の関連記事をご覧ください。

以下もご興味があるかもしれません:
  • MySQL の InnoDB のフルテーブルスキャン速度を大幅に向上させる方法
  • インデックススキャンを使用したMySQLソート
  • MySQL 8.0 のインデックス スキップ スキャン
  • MySQL のフルテーブルスキャンとインデックスツリースキャンの詳細な例

<<:  HTMLの基礎 HTMLの構造

>>:  PCとモバイルの適応の問題に対する迅速な解決策

推薦する

divの適応高さは残りの高さを自動的に埋めます

シナリオ 1: HTML: <div class="outer"> ...

デザイン: 意志の強いデザイナー

<br />長年の専門的なアートデザイン教育を通じて「美とは何か」を学びましたが、「美を...

MySQL 8.0.12 のインストールと設定方法のグラフィックチュートリアル

MySQL 8.0.12のインストールと設定方法を記録してみんなで共有します。 1. インストール1...

Vueプロジェクトがグラフィック検証コードを実装

この記事の例では、グラフィック検証コードを実装するためのVueプロジェクトの具体的なコードを参考まで...

Docker を使用した JMeter+Grafana+Influxdb 監視プラットフォームの構築に関する詳細なチュートリアル

Jmeter がネイティブの結果表示機能を提供していることは誰もが知っています。ネイティブの結果表示...

mysql bin-log ログファイルを sql ファイルに変換する方法

mysqlbinlogのバージョンを表示mysqlbinlog -V [--version] bin...

MySQLユーザー管理操作例の分析

この記事では、MySQL ユーザー管理操作について説明します。ご参考までに、詳細は以下の通りです。こ...

MYSQL データベースの基礎 - 結合操作の原理

結合では、ネスト ループ結合アルゴリズムが使用されます。ネスト ループ結合には 3 つの種類がありま...

MySQL フィールドで NOT NULL を使用する必要があるのはなぜですか?

私は最近新しい会社に入社したのですが、データベース設計にいくつか小さな問題があることに気付きました。...

JavaScript スクリプトが実行されるタイミングの詳細な説明

JavaScript スクリプトは HTML 内のどこにでも埋め込むことができますが、いつ呼び出され...

ウェブサイトのデザイン体験のための7つの異なるカラースキーム

ウェブサイト構築におけるカラーマッチングは非常に特殊であり、ウェブサイトのテーマ、感情、雰囲気などの...

RHEL7.5 mysql 8.0.11 インストールチュートリアル

この記事はRHEL7.5でのMySQL 8.0.11のインストールチュートリアルを記録しています。具...

Docker を使用した Hadoop クラスターのデプロイに関する詳細なチュートリアル

最近、社内に Hadoop テスト クラスターを構築したいので、docker を使用して Hadoo...

Linux 環境変数とプロセス アドレス空間の概要

目次Linux 環境変数とプロセスアドレス空間コードを通じて環境変数を取得するプロセスアドレス空間な...

js メモリ リークのシナリオ、それらを詳細に監視および分析する方法

目次序文どのような状況でメモリリークが発生する可能性がありますか? 1. 偶発的なグローバル変数2....