Rumah > Tutorial sistem > LINUX > teks badan

Ingat untuk memijak 'pit' MySQL dalam subquery

WBOY
Lepaskan: 2024-02-13 18:12:27
ke hadapan
799 orang telah melayarinya
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);
Salin selepas log masuk

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);
Salin selepas log masuk

Tetapi hakikatnya begini:

mysql> select count(*) from userinfo;
Salin selepas log masuk

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

mysql> select count(*) from article;
Salin selepas log masuk

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

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

记踩到 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);
Salin selepas log masuk

记踩到 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;
Salin selepas log masuk

记踩到 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!

sumber:linuxprobe.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan