フィールドの文字セットの違いによる MySQL のインデックス失敗の解決策

フィールドの文字セットの違いによる MySQL のインデックス失敗の解決策

インデックスとは何ですか?なぜインデックスを作成するのですか?

インデックスは、列に特定の値を持つ行をすばやく見つけるために使用されます。インデックスがない場合、MySQL は最初のレコードからテーブル全体を読み取って、関連する行を見つける必要があります。テーブルが大きいほど、データのクエリにかかる時間は長くなります。テーブル内のクエリ対象の列にインデックスがある場合、MySQL はすべてのデータを調べなくてもデータ ファイルを検索する場所にすばやく到達できるため、多くの時間を節約できます。

たとえば、20,000 件のレコードがあり、20,000 人の個人の情報が記録されている person テーブルがあるとします。各人の電話番号を記録する Phone フィールドがあります。ここで、電話番号が xxxx である人の情報を照会します。

インデックスがない場合、情報が見つかるまでテーブルは最初のレコードから次のレコードまで走査されます。

インデックスがある場合、Phone フィールドは特定の方法で保存されるため、このフィールドの情報を照会するときに、20,000 のデータ項目を走査することなく、対応するデータをすばやく見つけることができます。 MySQL には、BTREE と HASH の 2 種類のインデックス ストレージがあります。 つまり、ツリーまたはハッシュ値を使用してフィールドを保存します。詳細な検索方法を知るには、アルゴリズムを知る必要があります。ここで、インデックスの役割と機能を知る必要があります。

導入

今日は SQL ステートメントを書きました。関係するテーブルのデータ量は約 500,000 でした。クエリには 8 秒かかりました。これはあくまでテストサーバーのデータです。公式サーバーに置くと、実行するとすぐにクラッシュするはずです。

選択
 注文。いいえ、
 ガイド番号、
 注文.作成時間、
 sum(OrderItem.Quantity) AS 数量、
 Brand.NAME は BrandName として、
 メンバー.モバイル、
 配送先住所のストリート、
 エリア
から
 注文
内部結合 OrderItem ON Orders.GuidNo = OrderItem.OrderGuidNo
INNER JOIN ブランド ON ブランド.Id = Orders.BrandId
メンバーの内部結合メンバー on member.Id = 13
メンバーアドレスをメンバー.Id = メンバーアドレス.MemberId に内部結合します
どこ
 注文.GuidNo IN (
  選択
   注文支払.注文ガイド番号
  から
   支払い記録
  orderpayment を paymentrecord.`No` に LEFT JOIN します = orderpayment.PaymentNo
  どこ
   支払い記録.支払い方法 = 'メンバーカード'
  AND 支払記録.支払者 = 13
 )
グループ化
 ガイド番号;

そこでEXPLAINを使って解析してみると、Ordersテーブルがインデックスにヒットしていないことがわかりました。しかし、OrdersのGuidNoにはインデックスが設定されていたのですが、ヒットできませんでした。

解決プロセス

次に、上記のステートメントを 2 つのステートメントに分割します。まず、SQL ステートメントを次のように変更します。サブクエリ データを SQL ステートメントに直接書き込むと、クエリには 0.12 秒かかります。

選択
 注文。いいえ、
 ガイド番号、
 注文.作成時間、
 sum(OrderItem.Quantity) AS 数量、
 Brand.NAME は BrandName として、
 メンバー.モバイル、
 配送先住所のストリート、
 エリア
から
 注文
内部結合 OrderItem ON Orders.GuidNo = OrderItem.OrderGuidNo
INNER JOIN ブランド ON ブランド.Id = Orders.BrandId
メンバーの内部結合メンバー on member.Id = 13
メンバーアドレスをメンバー.Id = メンバーアドレス.MemberId に内部結合します
どこ
 注文.GuidNo IN (
  '0A499C5B1A82B6322AE99D107D4DA7B8'、
  '18A5EE6B1D4E9D76B6346D2F6B836442',
  '327A5AE2BACEA714F8B907865F084503',
  'B42B085E794BA14516CE21C13CF38187'、
  'FBC978E1602ED342E5567168E73F0602'
 )
グループ化
 ガイド番号

2番目: サブクエリのみを実行するSQLも0.1秒しかかかりません

選択
   注文支払.注文ガイド番号
  から
   支払い記録
  orderpayment を paymentrecord.`No` に LEFT JOIN します = orderpayment.PaymentNo
  どこ
   支払い記録.支払い方法 = 'メンバーカード'
  AND 支払記録.支払者 = 13

これで問題は明らかです。これはサブクエリと親クエリに関連する問題であるはずです。サブクエリは単独では非常に高速であるため、親クエリもサブクエリデータを直接使用すると非常に高速になりますが、2 つを組み合わせると非常に遅くなります。この問題は、大まかに言って、関連する 2 つのフィールド OrderGuidNo に起因します。

最後に、orderpayment テーブルと Orders テーブルの文字セットが異なることがわかります。一方のテーブルの文字セットは utf8_general_ci で、もう一方のテーブルの文字セットは utf8mb4_general_ci です。 (確認するまでわかりません。データベースでは、多くのテーブルに異なる文字セットがあることがわかります。)

orderpayment テーブルの文字セットとテーブル内の OrderGuidNo の文字セットを utf8_general_ci に変更します。

ALTER TABLE orderpayment DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; //テーブルの文字セットを変更します ALTER TABLE orderpayment CHANGE OrderGuidNo OrderGuidNo VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci; //フィールドの文字セットを変更します

次に EXPLAIN を使用して分析すると、インデックスが使用されていることがわかります。

実行すると、クエリには 0.112 秒かかりました。

要約する

上記はこの記事の全内容です。この記事の内容が皆さんの勉強や仕事に一定の参考学習価値を持つことを願っています。ご質問があれば、メッセージを残してコミュニケーションしてください。123WORDPRESS.COM を応援していただきありがとうございます。

以下もご興味があるかもしれません:
  • MySQL 文字セットの表示と変更のチュートリアル
  • MySQLの文字セットを変更する方法
  • MySQL データベースの文字化け問題の原因と解決策
  • MySQL の文字セット utf8 を utf8mb4 に変更する方法
  • 既存のMySQLデータベースの文字セットを統一する方法
  • MySQL 文字セットの文字化けとその解決方法
  • MySQL utf8mb4 文字セットの JDBC 処理の詳細な説明
  • MAC で MySQL のデフォルトの文字セットを utf8 に変更する方法
  • Docker で MySQL の文字セットを設定する方法
  • MySQLクエリの文字セットの不一致の問題を解決する方法
  • MySQLの文字セットと検証ルールの詳細な説明

<<:  JSを段階的に学ぶ方法についての簡単な説明

>>:  Linux LVM 論理ボリューム構成プロセス (作成、増加、削減、削除、アンインストール) の詳細な説明

推薦する

レスポンシブWebデザイン学習(2) — 動画をレスポンシブにすることはできるのか?

前回のエピソードレビュー:昨日は、ページがさまざまなデバイス サイズにどのように対応するかについて説...

AngularJSループオブジェクトプロパティで動的列を実装するアイデアの詳細な説明

動的な列を実現するための Angularjs ループ オブジェクト プロパティ利点: オブジェクトを...

DockerでGPUを使用するプロセスの詳細な説明

目次tf-gpu をダウンロード取得したtf-gpuイメージに基づいて独自のイメージを構築するイメー...

JS におけるメモリと変数の保存についての詳細な説明

目次序文JSマジックナンバー数値の保存バイナリ変換方法なぜ 0.1 + 0.2 !== 0.3 なの...

vue3.0+vant3.0の迅速なプロジェクト構築の実装

目次1. プロジェクトの構築2. Vue3 体験 + Vant 紹介2020年9月18日にvue.j...

MySQL サービス 1067 エラーの解決策: mysql 実行可能ファイルのパスを変更する

今日、MySQLサービス1067エラー問題に遭遇しました。システムアカウントを使用するように設定して...

Tomcat サービスに Java 起動コマンドを追加する方法

私の最初のサーバープログラム現在、オンラインゲームの書き方を学んでいるので、サーバーサイドのプログラ...

VMware 仮想マシンのインストール CentOS 8 (1905) システム チュートリアル ダイアグラム

世界的に有名な仮想マシン ソフトウェア VMware-workstation-full-15.5.0...

SQLの最適化では間違いがよく起こります。それはMySQLのExplain Planの使い方を理解していないからです。

目次1. 準備2. 説明計画の概要3. フィールドの詳細な説明4. パーティションクエリにはパーティ...

dockerコンテナは直接実行され、pingを介してパブリックIP操作を取得します。

コンテナを通じてローカル パブリック IP アドレスを取得します。ローカル IP アドレスを使用して...

HTML で選択ドロップダウン ボックスのコンテンツが不完全に表示され、部分的にカバーされる問題の解決策

今日、問題が発生しました。クエリ バーのドロップダウン ボックスの内容が長すぎて、一部が隠れてしまっ...

JavaScript 配列の include と Reduce の基本的な使用法

目次序文配列.プロトタイプ.includes文法パラメータ戻り値例配列プロトタイプの削減文法パラメー...

MySQLで重複行を削除する方法

SQL文 /* MySQL で重複行を削除するいくつかの方法 ---Chu Minfei ---20...

Reactフックとzarmコンポーネントライブラリ構成に基づいてh5フォームページを開発するためのサンプルコード

最近、React Hooks を zarm コンポーネント ライブラリと組み合わせて使用​​し、js...

航空機戦争ゲームを実装するためのJavaScript

この記事では、キャンバスとjsを使用して簡単な飛行機戦争を実装する方法を参考までに紹介します。具体的...