目次
結合クエリに対するインデックスの影響
データ準備
インデックス クエリ プロセスがあります。
SELECT * FROM t1 STRAIGHT_JOIN t2 ON (t1.a = t2.b);
ログイン後にコピー
" >
SELECT * FROM t1 STRAIGHT_JOIN t2 ON (t1.a = t2.b);
ログイン後にコピー
如何正确的写出 join 查询
驱动表的选择
什么是小表
ホームページ データベース mysql チュートリアル MySQL の結合クエリについて簡単に説明します

MySQL の結合クエリについて簡単に説明します

Nov 03, 2022 pm 04:49 PM
mysql

この記事では、mysql に関する関連知識を提供します。主に結合クエリに関する関連問題を紹介します。一緒に見てみましょう。皆様のお役に立てれば幸いです。

推奨される学習: mysql ビデオ チュートリアル

結合クエリに対するインデックスの影響

データ準備

2 つのテーブル t1 と t2 があるとします。どちらのテーブルにも主キーのインデックス ID とインデックス フィールド a および b フィールドがあり、インデックスはありません。次に、100 行のデータを t1 テーブルとt2 テーブル。実験用に 1000 行のデータを挿入します。

CREATE TABLE `t2` (
 `id` int NOT NULL,
 `a` int DEFAULT NULL,
 `b` int DEFAULT NULL,
 PRIMARY KEY (`id`),
 KEY `t2_a_index` (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

CREATE PROCEDURE **idata**()
BEGIN
  DECLARE i INT;
  SET i = 1;
  WHILE (i <h3 id="strong-インデックス-クエリ-プロセスがあります-strong"><strong>インデックス クエリ プロセスがあります。</strong></h3><p>クエリ SELECT * FROM t1 STRAIGHT_JOIN t2 ON (t1.a) を使用します。 =t2.a); 結合クエリ MYSQL オプティマイザーが希望どおりに実行できない可能性があるため、分析では、より直観的に観察するために代わりに STRAIGHT_JOIN を使用することを選択します。</p><p><mysql src="https://MySQL%20%E3%81%AE%E7%B5%90%E5%90%88%E3%82%AF%E3%82%A8%E3%83%AA%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E7%B0%A1%E5%8D%98%E3%81%AB%E8%AA%AC%E6%98%8E%E3%81%97%E3%81%BE%E3%81%99.php.cn/upload/article/000/000/067/64b9ac3a02f2e5095eba59bdfbcd23d6-2.png" alt="图 1" loading="lazy"></mysql> 図 1</p> <p>「t1 を駆動テーブルとして使用し、t2 を駆動テーブルとして使用していることがわかります。上の図の説明は、このクエリが t2 テーブルのインデックスであるフィールドを使用していることを示しているため、このステートメントの実行プロセスは次のようになります。 </p>
ログイン後にコピー
  • テーブル t1 からデータ r の行を読み取ります

  • #マッチングのためにデータ r からテーブル t2 にフィールド a を取得します

  • t2 テーブル内の条件を満たす行を取り出し、結果セットの一部として r を含む行を形成します

  • 手順 1 ~ 3 を繰り返します。テーブル t1 がデータをループするまで

このプロセスはインデックス ネストループ結合と呼ばれます。このプロセスでは、ドライバー テーブル t1 はテーブル全体のスキャンを実行します。 t1 テーブル、このスキャン行の数は 100 で、結合クエリを実行するときは、t1 テーブルの各行を t2 テーブルで検索する必要があります。インデックス ツリー検索が使用されます。構築するデータは 1 対であるため、 -one 対応、各検索は 1 行のみをスキャンします。つまり、t2 テーブルも合計 100 行をスキャンします。クエリ プロセス全体でスキャンされる行の合計数は 100 100=200 行です。

#No Index query process

SELECT * FROM t1 STRAIGHT_JOIN t2 ON (t1.a = t2.b);
ログイン後にコピー

図 2

t2 テーブルのフィールド B にはインデックスがないことがわかります。 , 上記の SQL によると、実行中に、t1 が t2 と一致するたびにテーブル全体のスキャンを実行する必要があります。このように、t2 は最大 100 回スキャンする必要があり、スキャンの合計数は 100*1000 = 100,000 行になります。

もちろん、このクエリ結果は、構築した 2 つのテーブルが小さいという事実に基づいています。テーブルが 100,000 行ある場合、100 億行をスキャンする必要があります。これはひどいことです。

2. 理解する

ネストされたループ結合のブロック

##ネストされたループ結合のブロック

クエリ プロセス つまり、駆動テーブルにはインデックスがありません。なぜこのようなことが起こったのでしょうか?

実際、駆動テーブルに利用可能なインデックスがない場合、アルゴリズム プロセスは次のようになります:

t1 のデータをスレッド メモリの join_buffer に読み取ります。上で書いたのは select * from なので、t1 テーブル全体をメモリに入れるのと同じです;
  • t2 をスキャンするプロセスは、実際には t2 の各行を取り出して照合します。 join_buffer 内の行とデータが比較され、結合条件を満たすデータが結果セットの一部として返されます。

したがって、結合バッファーの使用を説明する図 2 の追加部分と組み合わせると、この手がかりを見つけることができます。プロセス全体で、両方のテーブル t1と t2 が完了しました。テーブル全体のスキャンなので、スキャンされる行数は 100 1000 = 1100 行です。join_buffer は順序付けされていない配列で構成されているため、テーブル t2 の各行に対して 100 回の判断を行う必要があり、合計100回の判定をメモリ内で行う必要があり、判定回数は100*1000=10万回となりますが、この10万回をメモリ内で行うため、非常に高速でパフォーマンスが良くなります。

Join_buffer

上記のことからわかるように、インデックスがないと、MySQL はループ判定のためにデータをメモリに読み込むため、このメモリは決して無制限ではありません。使用する場合は、パラメータ join_buffer_size を使用する必要があります。値のデフォルト サイズは、以下に示すように 256k です。
SHOW VARIABLES LIKE '%join_buffer_size%';
ログイン後にコピー

図 4

If query データ一度に読み込むには大きすぎて、一部のデータ(80件)しか読み込めない場合、クエリ処理は次のようになります

  • 扫描表 t1,顺序读取数据行放入 join_buffer 中,直至加载完第 80 行满了

  • 扫描表 t2,把 t2 表中的每一行取出来跟 join_buffer 中的数据做对比,将满足条件的数据作为结果集的一部分返回

  • 清空 join_buffer

  • 继续扫描表 t1,顺序读取剩余的数据行放入 join_buffer 中,执行步骤 2

这个流程体现了算法名称中 Block 的由来,分块 join,可以看出虽然查询过程中 t1 被分成了两次放入 join_buffer 中,导致 t2 表被扫描了 2次,但是判断等值条件的次数还是不变的,依然是(80+20)*1000=10 万次。

所以这就是有时候 join 查询很慢,有些大佬会让你把 join_buffer_size 调大的原因。

如何正确的写出 join 查询

驱动表的选择

  • 有索引的情况下

在这个 join 语句执行过程中,驱动表是走全表扫描,而被驱动表是走树搜索。

假设被驱动表的行数是 M,每次在被驱动表查询一行数据,先要走索引 a,再搜索主键索引。每次搜索一棵树近似复杂度是以 2为底的 M的对数,记为 log2M,所以在被驱动表上查询一行数据的时间复杂度是 2*log2M。

假设驱动表的行数是 N,执行过程就要扫描驱动表 N 行,然后对于每一行,到被驱动表上 匹配一次。因此整个执行过程,近似复杂度是 N + N2log2M。显然,N 对扫描行数的影响更大,因此应该让小表来做驱动表。

  • 那没有索引的情况

上述我知道了,因为 join_buffer 因为存在限制,所以查询的过程可能存在多次加载 join_buffer,但是判断的次数都是 10 万次,这种情况下应该怎么选择?

假设,驱动表的数据行数是 N,需要分 K 段才能完成算法流程,被驱动表的数据行数是 M。这里的 K不是常数,N 越大 K就越大,因此把 K 表示为λ*N,显然λ的取值范围 是 (0,1)。

扫描的行数就变成了 N+λNM,显然内存的判断次数是不受哪个表作为驱动表而影响的,而考虑到扫描行数,在 M和 N大小确定的情况下,N 小一些,整个算是的结果会更小,所以应该让小表作为驱动表

总结:真相大白了,不管是有索引还是无索引参与 join 查询的情况下都应该是使用小表作为驱动表。

什么是小表

还是以上面表 t1 和表 t2 为例子:

SELECT * FROM t1 STRAIGHT_JOIN t2 ON t1.b = t2.b WHERE t2.id <p>上面这两条 SQL 我们加上了条件 t2.id </p><p>再看另一组:</p><pre class="brush:php;toolbar:false">SELECT t1.b,t2.* FROM t1 STRAIGHT_JOIN t2 ON t1.b = t2.b WHERE t2.id <p>这个例子里,表 t1 和 t2 都是只有 100 行参加 join。 但是,这两条语句每次查询放入 join_buffer 中的数据是不一样的: 表 t1 只查字段 b,因此如果把 t1 放到 join_buffer 中,只需要放入字段 b 的值; 表 t2 需要查所有的字段,因此如果把表 t2 放到 join_buffer 中的话,就需要放入三个字 段 id、a 和 b。</p><p>这里,我们应该选择表 t1 作为驱动表。也就是说在这个例子里,”只需要一列参与 join 的 表 t1“是那个相对小的表。</p><p>结论:</p><p>在决定哪个表做驱动表的时候,应该是两个表按照各自的条件过滤,过 滤完成之后,计算参与 join 的各个字段的总数据量,数据量小的那个表,就是“小表”, 应该作为驱动表。</p><p>推荐学习:<a href="https://www.php.cn/course/list/51.html" target="_blank" textvalue="mysql视频教程">mysql视频教程</a></p>
ログイン後にコピー

以上がMySQL の結合クエリについて簡単に説明しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

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

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

MySQL:簡単な学習のためのシンプルな概念 MySQL:簡単な学習のためのシンプルな概念 Apr 10, 2025 am 09:29 AM

MySQLは、オープンソースのリレーショナルデータベース管理システムです。 1)データベースとテーブルの作成:createdatabaseおよびcreateTableコマンドを使用します。 2)基本操作:挿入、更新、削除、選択。 3)高度な操作:参加、サブクエリ、トランザクション処理。 4)デバッグスキル:構文、データ型、およびアクセス許可を確認します。 5)最適化の提案:インデックスを使用し、選択*を避け、トランザクションを使用します。

Navicatプレミアムの作成方法 Navicatプレミアムの作成方法 Apr 09, 2025 am 07:09 AM

NAVICATプレミアムを使用してデータベースを作成します。データベースサーバーに接続し、接続パラメーターを入力します。サーバーを右クリックして、[データベースの作成]を選択します。新しいデータベースの名前と指定された文字セットと照合を入力します。新しいデータベースに接続し、オブジェクトブラウザにテーブルを作成します。テーブルを右クリックして、データを挿入してデータを挿入します。

phpmyadminを開く方法 phpmyadminを開く方法 Apr 10, 2025 pm 10:51 PM

次の手順でphpmyadminを開くことができます。1。ウェブサイトコントロールパネルにログインします。 2。phpmyadminアイコンを見つけてクリックします。 3。MySQL資格情報を入力します。 4.「ログイン」をクリックします。

MySQLおよびSQL:開発者にとって不可欠なスキル MySQLおよびSQL:開発者にとって不可欠なスキル Apr 10, 2025 am 09:30 AM

MySQLとSQLは、開発者にとって不可欠なスキルです。 1.MYSQLはオープンソースのリレーショナルデータベース管理システムであり、SQLはデータベースの管理と操作に使用される標準言語です。 2.MYSQLは、効率的なデータストレージと検索機能を介して複数のストレージエンジンをサポートし、SQLは簡単なステートメントを通じて複雑なデータ操作を完了します。 3.使用の例には、条件によるフィルタリングやソートなどの基本的なクエリと高度なクエリが含まれます。 4.一般的なエラーには、SQLステートメントをチェックして説明コマンドを使用することで最適化できる構文エラーとパフォーマンスの問題が含まれます。 5.パフォーマンス最適化手法には、インデックスの使用、フルテーブルスキャンの回避、参加操作の最適化、コードの読み取り可能性の向上が含まれます。

NavicatでMySQLへの新しい接続を作成する方法 NavicatでMySQLへの新しい接続を作成する方法 Apr 09, 2025 am 07:21 AM

手順に従って、NAVICATで新しいMySQL接続を作成できます。アプリケーションを開き、新しい接続(CTRL N)を選択します。接続タイプとして「mysql」を選択します。ホスト名/IPアドレス、ポート、ユーザー名、およびパスワードを入力します。 (オプション)Advanced Optionsを構成します。接続を保存して、接続名を入力します。

SQLが行を削除した後にデータを回復する方法 SQLが行を削除した後にデータを回復する方法 Apr 09, 2025 pm 12:21 PM

データベースから直接削除された行を直接回復することは、バックアップまたはトランザクションロールバックメカニズムがない限り、通常不可能です。キーポイント:トランザクションロールバック:トランザクションがデータの回復にコミットする前にロールバックを実行します。バックアップ:データベースの定期的なバックアップを使用して、データをすばやく復元できます。データベーススナップショット:データベースの読み取り専用コピーを作成し、データが誤って削除された後にデータを復元できます。削除ステートメントを使用して注意してください:誤って削除されないように条件を慎重に確認してください。 WHERE句を使用します:削除するデータを明示的に指定します。テスト環境を使用:削除操作を実行する前にテストします。

単一のスレッドレディスの使用方法 単一のスレッドレディスの使用方法 Apr 10, 2025 pm 07:12 PM

Redisは、単一のスレッドアーキテクチャを使用して、高性能、シンプルさ、一貫性を提供します。 I/Oマルチプレックス、イベントループ、ノンブロッキングI/O、共有メモリを使用して同時性を向上させますが、並行性の制限、単一の障害、および書き込み集約型のワークロードには適していません。

MySQL:世界で最も人気のあるデータベースの紹介 MySQL:世界で最も人気のあるデータベースの紹介 Apr 12, 2025 am 12:18 AM

MySQLはオープンソースのリレーショナルデータベース管理システムであり、主にデータを迅速かつ確実に保存および取得するために使用されます。その実用的な原則には、クライアントリクエスト、クエリ解像度、クエリの実行、返品結果が含まれます。使用法の例には、テーブルの作成、データの挿入とクエリ、および参加操作などの高度な機能が含まれます。一般的なエラーには、SQL構文、データ型、およびアクセス許可、および最適化の提案には、インデックスの使用、最適化されたクエリ、およびテーブルの分割が含まれます。

See all articles