MySQLが日付フィールドインデックスを使用しない理由の要約

MySQLが日付フィールドインデックスを使用しない理由の要約

背景

テーブルでは、dataTime フィールドは varchar 型に設定され、保存されるデータは日付形式で、フィールドにインデックスが設定されます。しかし、ログ レコードには、このテーブルに関する遅いクエリがあります。クエリステートメントは次のとおりです。
select * from digitaltwin_meteorological where dataTime > '2021-10-15';
EXPLAIN は SQL ステートメントを分析し、SQL ステートメントが完全なテーブルスキャンを実行していることを検出します。 SQL で dataTime インデックス列が使用されるのはなぜですか。また、テーブル全体のスキャンが実行される理由はなぜですか。

探検する

1:当初、dataTime フィールドの型が varchar であると考えられていたため、MySQL は日付のサイズ順ではなく文字列順にインデックスをソートし、範囲クエリを実行するときに日付順にインデックス範囲のパーティション分割を実行できませんでした。そこで、dataTime を datatime 型に変更してステートメントを分析したところ、依然として完全なテーブルスキャンが行われていることがわかりました。

2:クエリ条件の値を変更する

 digitaltwin_meteorological から count(*) を選択します。ここで、dataTime > '2021-10-15' です。

実行結果は3910です。

EXPLAIN デジタルツインのmeteorologicalから*を選択し、dataTime > '2021-10-15'を選択します。

SQL ステートメントの分析結果は、完全なテーブルスキャンです。

ここに画像の説明を挿入

レコードの数を確認するために、クエリ条件を 16 に変更します。

 digitaltwin_meteorological から count(*) を選択します。ここで、dataTime > '2021-10-16' です。

クエリ結果は 2525 です。16 番のクエリ ステートメントを分析してみましょう。

EXPLAIN デジタルツインのmeteorologicalから*を選択し、dataTime > '2021-10-16'を選択します。

実行結果は、インデックスを使用する範囲クエリです。

ここに画像の説明を挿入

このことから、クエリされるレコードの数が多い場合、MySQL はフル テーブル スキャンの方が効率的であると判断してフル テーブル スキャンを実行することがわかります。クエリ内のレコードが少ない場合、MySQL はインデックス クエリを使用します。
テーブル内のデータの総量は 19714 レコードです。つまり、2525/19714 = 13% の場合、MySQL はインデックス クエリを使用します。 3910/19714=20% の場合、MySQL は完全なテーブルスキャンを実行します。

3: dataTime を datetime データ型に変更した場合、クエリ条件に引用符を追加する必要がありますか? dataTime クエリ条件の引用符を削除して結果を確認します。

EXPLAIN digitaltwin_meteorological から * を選択し、dataTime > 2021-10-16 を指定します。

ここに画像の説明を挿入
引用符を削除すると、再び完全なテーブルスキャンになることがわかります。したがって、フィールド タイプが varchar か datetime かに関係なく、クエリ条件の値は引用符で囲む必要があります。引用符がない場合、MySQL はこの値に対して何らかの計算を実行します。実際、引用符がない場合、2021-10-16 は 16 日の日付ではなくなります。次の SQL を見てみましょう。

 digitaltwin_meteorological から count(*) を選択します。ここで、dataTime > 2021-10-16 です。

計算結果は 19714 となり、これはテーブル全体のデータです。そのため、datetime クエリ条件も引用符で囲む必要があります。

4: 上記の分析はすべて、datetime 型の場合の dataTime に関するものです。元のフィールド タイプは varchar なので、これを varchar タイプに変更すると、上記の結論は依然として当てはまりますか? タイプを変更して、SQL を再度実行します。

EXPLAIN select * from digitaltwin_meteorological where dataTime > '2021-10-16';

ここに画像の説明を挿入

varchar 型に変更すると、クエリ 16 は範囲スキャンではなくフル テーブル スキャンになることがわかります。
条件を 17 番に変更して実行結果を確認します。

EXPLAIN デジタルツインのmeteorologicalから*を選択し、dataTime > '2021-10-17'を選択します。

ここに画像の説明を挿入

17日のクエリではインデックスクエリが使用されました。 17日のデータ量は1749であることがわかります。
したがって、フィールド タイプが varchar の場合、1749/19714 = 9% のケースでインデックスが使用され、2525/19714 = 13% のケースでテーブル全体がスキャンされます。
つまり、データ型が datetime の場合、クエリ結果がテーブル全体のデータの 13% を占めるとインデックス クエリが実行され、データ型が varchar の場合、クエリ結果がテーブル全体のデータの 13% を占めるとテーブル全体のスキャンが実行されます。これが、日付タイプを varchar ではなく datetime に設定する理由の 1 つです。

要約する

上記の分析を通じて、次のような結論を導き出すことができます。
1. 範囲クエリでは、クエリされるデータの量が特定の範囲に達すると、MySQL は完全なテーブル スキャンの方が効率的であると判断し、インデックスではなく完全なテーブル スキャンを実行します。
2. クエリを実行するときは、datetime フィールド タイプの値も引用符で囲む必要があります。そうしないと、MySQL は日付で処理しません。
3. 日付形式のデータの場合、varchar 型に設定すると、範囲クエリでインデックス クエリまたはフル テーブル スキャンを使用するための臨界値は、datetime 型クエリでインデックス クエリまたはフル テーブル スキャンを使用するための臨界値よりも低くなります。そのため、日付型データを datetime 型に設定すると、インデックス クエリが使用される可能性が高くなります。

MySQL が日付フィールド インデックスを使用しない理由に関するこの記事はこれで終わりです。MySQL 日付フィールド インデックスに関するより関連性の高いコンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • MySQLのどのフィールドがインデックスに適しているかについての簡単な説明
  • フィールドの文字セットの違いによる MySQL のインデックス失敗の解決策
  • MySQL のフィールドに一意のインデックスを追加および削除する方法
  • Mysqlはテーブルフィールドまたはインデックスが存在するかどうかを判断します

<<:  CSS スタイルで一般的なグラフィック効果を示すサンプルコード

>>:  入力ボックスのプレースホルダーテキストのデフォルトの色を変更する -webkit-input-placeholder メソッド

推薦する

HTTP 戻りコード一覧(中国語と英語の説明)

httpリターンコードリスト(以下は概要です)詳細な中国語の説明についてはここをクリックしてくださ...

MySQL における := と = の違いをグラフィカルに紹介

:= と = の違い=設定および更新の場合にのみ、:= と同じ効果、つまり代入効果があり、それ以外の...

CSSコンテンツ属性の具体的な使用法

コンテンツ属性は通常、::before および ::after 疑似要素で使用され、疑似要素のコンテ...

RedisとMySQLの違いを簡単に説明してください

MySQL はディスクに保存される永続的なストレージであり、取得には一定の IO が伴うことはご存じ...

MySQL データベースの最適化: インデックスの実装原則と使用状況の分析

この記事では、例を使用して、MySQL データベースの最適化のためのインデックス実装の原則と使用方法...

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

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

Dockerコンテナでの静的ウェブサイトレイアウトの実装

サーバーの配置数日間無料で使用できるクラウドサーバー(Alibaba Cloud、Huawei Cl...

データ構造 - ツリー (III): 多方向検索ツリー B ツリー、B+ ツリー

多方向探索ツリー完全二分木の高さ: O(log2N)、ここで2は対数完全なM方向探索木の高さ: O(...

Ubuntu 20.04でルートアカウントを有効にする方法

Ubuntu 20.04 をインストールした後、デフォルトでは root アカウントのログイン権限が...

フレームセットの共通プロパティ(フレームとウィンドウの分割)

フレームとは、Web ページ画面を複数のフレームに分割したもの(複数の Web ページという形で表示...

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

Centos6.4 で mysql5.7.18 をインストールするための具体的な手順が全員に共有され...

MySQLのスイッチングデータ保存ディレクトリの実装方法

MySQLのスイッチングデータ保存ディレクトリの実装方法今日、仕事中に、mysql が保存されている...

JS ベースの Ajax 同時リクエスト制御を実装する方法

目次序文Ajax シリアルおよびパラレルAjaxの同時リクエスト制御のための2つのソリューションPr...

Vue Nativeを使用したモバイルアプリケーションの構築プロセスの完全な記録

目次序文Vue Nativeの機能宣言的レンダリング双方向バインディングVue.js エコシステムの...

dockerにros2をインストールするための詳細な手順

目次メイントピック1. UbuntuにDockerをインストールする2. DockerにROS2-F...