ホームページ  >  記事  >  システムチュートリアル  >  サブクエリではMySQLの「落とし穴」を踏むことを忘れないでください

サブクエリではMySQLの「落とし穴」を踏むことを忘れないでください

WBOY
WBOY転載
2024-02-13 18:12:27771ブラウズ

#########序文#########

MySQL はプロジェクトでよく使用されるデータベースであり、クエリでもよく使用されます。最近のプロジェクトのデバッグ中に、予期しない選択クエリが発生しました。実際には 33 秒かかりました。 1. テーブル構造

1. ユーザー情報テーブル

2.記事テーブル

记踩到 MySQL in 子查询的“坑”

リーリー 上記の SQL を初めて見たとき、これは非常に単純なサブクエリであると思われるかもしれません。まず author_id を調べてから、 in を使用してクエリします。

関連するインデックスがあれば非常に高速ですが、逆アセンブルすると以下のようになります。 リーリー

记踩到 MySQL in 子查询的“坑”しかし、事実は次のとおりです:

リーリー

リーリー

リーリー

记踩到 MySQL in 子查询的“坑”

33秒记踩到 MySQL in 子查询的“坑”

!

记踩到 MySQL in 子查询的“坑”なぜこんなに遅いのでしょうか?

3. 問題の原因

公式ドキュメントの説明: in 句はクエリ時に存在するように変換されることがあり、レコードごとにスキャンされます (バージョン 5.5 に存在し、5.6 で最適化されました)。
###参照する:### https://dev.mysql.com/doc/refman/5.5/en/subquery-optimization.html

4. 解決策 (バージョン 5.5)记踩到 MySQL in 子查询的“坑”

1.一時テーブルを使用します

リーリー
2.結合を使用します

リーリー

记踩到 MySQL in 子查询的“坑”

5. 補足

バージョン 5.6 は、[4] の一時テーブルと同じ方法でサブクエリ用に最適化されています。公式ドキュメントを参照してください: 记踩到 MySQL in 子查询的“坑”

実体化が使用されていない場合、オプティマイザは非相関サブクエリを相関サブクエリとして書き換える場合があります。 たとえば、次の IN サブクエリは相関関係がありません (where_condition には t2 の列のみが含まれ、t1 は含まれません):
select * from t1

where t1.a in (t2 where where_condition から t2.b を選択);

オプティマイザ はこれを EXISTS 相関サブクエリとして書き換える可能性があります

:

select * from t1

where が存在します (t2 where_condition および t1.a=t2.b から t2.b を選択します);

サブクエリの実体化

一時テーブルを使用すると、そのような書き換えが回避され、外部クエリの行ごとに 1 回ではなく、サブクエリを 1 回だけ実行できるようになります.

https://dev.mysql.com/doc/refman/5.6/en/subquery-materialization.html

この記事は WeChat 公開アカウントからのものです: HULK 最前線の技術トーク

以上がサブクエリではMySQLの「落とし穴」を踏むことを忘れないでくださいの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はlinuxprobe.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。