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 秒)

[email protected]: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とモバイルの適応の問題に対する迅速な解決策

推薦する

Mysql の一般的なベンチマーク コマンドの概要

mysqlslap共通パラメータの説明–auto-generate-sql システムはテスト用のSQ...

Mysql の追加、削除、変更、クエリステートメントのシンプルな実装

Mysql の追加、削除、変更、クエリステートメントのシンプルな実装追加されたレコード: テーブル名...

Dockerで構築されたコンテナにpingツールをインストールする

Centos や Ubuntu など、Docker が pull する Base イメージは最もシン...

CocosCreator で物理エンジン ジョイントを使用する方法

目次マウスジョイント マウスジョイント距離ジョイント距離ジョイントモータージョイント直動ジョイント変...

Tomcat が設定ファイルを外部に配置するためのソリューション

質問通常の開発では、プロジェクトを Tomcat にデプロイする場合、プロジェクトを war パッケ...

CSS 3.0とビデオを組み合わせることでクリエイティブなオープニング効果を実現

CSS 3.0 とビデオを組み合わせて実現したクリエイティブなオープニングをご紹介します。効果は次の...

MySQL データベースは SQL ステートメントを知っている必要があります (拡張バージョン)

拡張版です。質問とSQL文は以下の通りです。ユーザー テーブルを作成し、id、name、gender...

MySQL クエリ データベース容量方法手順

すべてのデータベースの合計サイズを照会する方法は次のとおりです。 mysql> informa...

VSCode の JS フォーマットでセミコロンを自動的に追加または削除する方法について

導入js コード文の末尾にセミコロンを追加しても追加しなくても問題ありません。一般的に、チームで開発...

ノードイベントループとメッセージキューの分析

目次非同期とは何ですか?なぜ非同期性が必要なのでしょうか?非同期IOとは何ですか?イベントループとは...

Node.js+express+socket でオンラインのリアルタイム多人数チャットルームを実現

この記事では、オンラインリアルタイム多人数チャットルームを実現するためのNode.js+expres...

MySQLデータベースのマスタースレーブレプリケーションの原理と機能の分析

目次1. データベースのマスター/スレーブ分類: 2. MySQL マスタースレーブの紹介3. マス...

HTML+SassはHambergurMenu(ハンバーガーメニュー)を実装します

先日、外国人の方がHTML+CSSを使ってHamburgerMenuを実装している動画を見ました。最...

タグが新しいページを開くかどうかという問題。主要ウェブサイトの開設状況をまとめました

a タグが新しいページを開くかどうか: (1)百度百科事典:ヘッダーが異なる場合は新しいページが開き...

Centos8 で yum を使用して mongodb 4.2 をインストールする方法

1. リポジトリファイルを作成するmongodb の公式インストール ドキュメントを参照し、次のスク...