接続操作では、駆動テーブルと被駆動テーブルの関連付け条件をその後に置きます。テーブルと駆動テーブルを追加しました。駆動テーブルのフィルター条件が on または where の後に配置された場合、エラーは報告されませんが、取得される結果セットは異なりますか? ? ?
ご存知のとおり、mysql は Nested-Loop Join (ネストループ結合、現時点では最適化アルゴリズムを考慮していません) に基づいています。 ) テーブル間の接続操作を実行するアルゴリズム 一般的なプロセスは次のとおりです。
ドライバー テーブルを選択し、ドライバー テーブルに関連するフィルター条件を使用して単一テーブルを実行します。ドライバー テーブルに対するクエリ;
クエリされたドライバー テーブル内の各レコードについて、駆動テーブル内の一致するレコードを検索します。
疑似コードは次のとおりです。
for each row in t1 { // 遍历满足对t1单表查询结果集中的每一条纪录 for each row in t2 { // 对于某条t1纪录,遍历满足对t2单表查询结果集中的每一条纪录 if row satisfies join conditions, send to client } }
記述した SQL ステートメントは次のように最適化されます。その後、オプティマイザは実行のためにエグゼキュータに渡され、show warnings コマンドを使用すると、オプティマイザによって最適化された SQL を取得できます。
テーブルの構造は次のとおりです:
CREATE TABLE `student` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `stu_code` varchar(20) NOT NULL DEFAULT '', `stu_name` varchar(30) NOT NULL DEFAULT '', `stu_sex` varchar(10) NOT NULL DEFAULT '', `stu_age` int(10) NOT NULL DEFAULT '0', `stu_dept` varchar(30) NOT NULL DEFAULT '', PRIMARY KEY (`id`) USING BTREE, UNIQUE KEY `uq_stu_code` (`stu_code`) ) ENGINE=InnoDB AUTO_INCREMENT=43 DEFAULT CHARSET=utf8mb4 CREATE TABLE `course` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `cou_code` varchar(20) NOT NULL DEFAULT '', `cou_name` varchar(50) NOT NULL DEFAULT '', `cou_score` int(10) NOT NULL DEFAULT '0', `stu_code` varchar(20) NOT NULL DEFAULT '', PRIMARY KEY (`id`) USING BTREE, KEY `idx_stu_code_cou_code` (`stu_code`,`cou_code`) ) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8mb4
テーブルのデータは次のとおりです:
sql の違いは次のとおりです:
select * from student inner join course on student.stu_code = course.stu_code and student.stu_code >= 3 and course.cou_score >= 80;
explain sql コマンドを実行します:
show warnings コマンドを実行します:
分析: 表示警告の分析から、内部結合接続の場合、オプティマイザーによる最適化の後、on 接続条件は where! に変換されます。つまり、内部接続の where と on は
と同等です。
sql の違いは次のとおりです:
select * from student left join course on student.stu_code = course.stu_code where student.stu_code >= 3;
explain sql コマンドを実行します:
show warnings コマンドを実行します:
結果セット:
分析: Explain 分析から、student がドライバー テーブルとして使用されます、student.stu_code >= 3 は、テーブル全体のスキャンを実行するためのフィルター条件として使用され、その後、クエリされた各レコードの Student.stu_code (つまり、on 条件内) がフィルター条件として使用され、駆動テーブル コースでの単一テーブル クエリ。
sql は次のとおりです:
select * from student left join course on student.stu_code = course.stu_code and student.stu_code >= 3;
explain SQL コマンドを実行します:
show warnings コマンドを実行:
## 結果セット:
結果セットから、student.stu_code >= 3 は有効になりません。なぜですか?分析: Explain 分析からわかるように、student はテーブル全体のスキャンを実行するドライバー テーブルとして使用され、その後、クエリされた各テーブルの Student.stu_code と Student.stu_code が使用されます。 Record are >= 3 (つまり、on 条件内) は、駆動テーブルが単一テーブル クエリを実行できるようにするフィルター条件として使用されます。現時点では、student.stu_code >= 3 はフィルターされません。ドライバー テーブルに接続する場合にのみ有効となり、クエリは一致するレコードを見つけることができず、NULL を返します。
sql は次のとおりです:
select * from student left join course on student.stu_code = course.stu_code and course.cou_score >= 80;
explain SQL コマンドを実行します:
show warnings コマンドを実行:
##結果セット:# ##################################
分析: Explain 分析からわかるように、テーブル全体のスキャンを実行するための駆動テーブルとして Student が使用され、クエリされた各レコードの Student.stu_code と course.cou_score は次のようになります。 on 条件の = 80 (つまり、) は、駆動テーブルが単一テーブル クエリを実行できるようにするためのフィルター条件として使用されます。
sqlは次のとおりです:
explain sql コマンドを実行します:
show warnings コマンドを実行します:
結果セット:
ショーの警告の分析からですか?左結合接続が内部結合接続になりますか?
分析: show warnings 分析から、駆動テーブルの where にフィルター条件がある場合、左結合が無効になり、内部結合接続に最適化されることがわかります。したがって、 駆動テーブルのフィルター条件は、where
の代わりに配置する必要があります。
以上がMySQLテーブル接続の実行プロセスは何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。