Rumah  >  Artikel  >  Tutorial sistem  >  Ingat untuk memijak "pit" MySQL dalam subquery

Ingat untuk memijak "pit" MySQL dalam subquery

WBOY
WBOYke hadapan
2024-02-13 18:12:27771semak imbas
Kata Pengantar

MySQL ialah pangkalan data yang biasa digunakan dalam projek, dan dalam pertanyaan juga sangat biasa digunakan. Semasa penyahpepijatan projek baru-baru ini, saya menemui pertanyaan pilihan yang tidak dijangka, yang sebenarnya mengambil masa 33 saat!

1. Struktur meja

1. jadual maklumat pengguna

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

2. jadual artikel

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

select*fromuserinfowhereidin(selectauthor_idfromartilcewheretype=1);

Apabila anda mula-mula melihat SQL di atas, anda mungkin berfikir bahawa ia adalah subkueri yang sangat mudah. Mula-mula ketahui author_id, dan kemudian gunakan untuk menanyakannya.

Jika ada indeks yang berkaitan, ia akan menjadi sangat cepat dari segi pembongkaran, ia adalah seperti berikut:

1.selectauthor_idfromartilcewheretype=1;  2.select*fromuserinfowhereidin(1,2,3);

Tetapi hakikatnya begini:

mysql> select count(*) from userinfo;

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

mysql> select count(*) from article;

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

mysql> select id,username from userinfo where id in (select author_id from article where type = 1);

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

33 saat! Kenapa lambat sangat?

3. Punca masalah
Penjelasan dokumen rasmi: Klausa dalam kadangkala ditukar kepada wujud apabila membuat pertanyaan, dan dilalui rekod mengikut rekod (sedia ada dalam versi 5.5, dioptimumkan dalam 5.6).

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

Rujukan:

https://dev.mysql.com/doc/refman/5.5/en/subquery-optimization.html

4. Penyelesaian (versi 5.5)

1. Gunakan meja sementara

select id,username from userinfo

where id in (select author_id from

(select author_id from article where type = 1) as tb);

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

2. Guna join

select a.id,a.username from userinfo a, article b

where a.id = b.author_id and b.type = 1;

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

5 Versi 5.6 telah dioptimumkan untuk subkueri Kaedahnya adalah sama dengan kaedah jadual sementara dalam [4]. Jika pewujudan tidak digunakan, pengoptimum kadangkala menulis semula subkueri yang tidak berkorelasi sebagai subkueri berkorelasi.

Sebagai contoh, subkueri IN berikut tidak berkorelasi (di mana_condition hanya melibatkan lajur dari t2 dan bukan t1):

pilih * daripada t1

di mana t1.a masuk (pilih t2.b daripada t2 di mana di mana_syarat);

Pengoptimum

mungkin menulis semula ini sebagai subquery berkorelasi EXISTS

:

pilih * daripada t1

di mana wujud (pilih t2.b daripada t2 di mana where_condition dan t1.a=t2.b);

Penciptaan subkueri

menggunakan jadual sementara mengelakkan penulisan semula sedemikian dan memungkinkan untuk melaksanakan subkueri hanya sekali dan bukannya sekali setiap baris pertanyaan luar

.

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

Artikel itu datang dari akaun awam WeChat: HULK rundingan teknikal barisan hadapan

Atas ialah kandungan terperinci Ingat untuk memijak "pit" MySQL dalam subquery. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:linuxprobe.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam