Saya punya beberapa duplikat di database yang ingin saya periksa, jadi apa yang saya lakukan untuk melihat duplikat yang mana, saya lakukan ini:
SELECT relevant_field
FROM some_table
GROUP BY relevant_field
HAVING COUNT(*) > 1
Dengan cara ini, saya akan mendapatkan semua baris dengan relevan_field terjadi lebih dari satu kali. Permintaan ini membutuhkan milidetik untuk dieksekusi.
Sekarang, saya ingin memeriksa setiap duplikat, jadi saya pikir saya bisa PILIH setiap baris di some_table dengan relevan_field dalam permintaan di atas, jadi saya suka ini:
SELECT *
FROM some_table
WHERE relevant_field IN
(
SELECT relevant_field
FROM some_table
GROUP BY relevant_field
HAVING COUNT(*) > 1
)
Ini ternyata sangat lambat untuk beberapa alasan (butuh beberapa menit). Apa sebenarnya yang terjadi di sini untuk membuatnya sepelan itu? relevan_field diindeks.
Akhirnya saya mencoba membuat tampilan "temp_view" dari kueri pertama (SELECT relevant_field FROM some_table GROUP BY relevant_field HAVING COUNT(*) > 1)
, dan kemudian membuat kueri kedua seperti ini:
SELECT *
FROM some_table
WHERE relevant_field IN
(
SELECT relevant_field
FROM temp_view
)
Dan itu bekerja dengan baik. MySQL melakukan ini dalam beberapa milidetik.
Adakah ahli SQL di sini yang dapat menjelaskan apa yang terjadi?
Jawaban:
Tulis ulang permintaan menjadi ini
Saya pikir
st2.relevant_field
harus di pilih, karena kalau tidakhaving
klausa akan memberikan kesalahan, tapi saya tidak 100% yakinJangan pernah gunakan
IN
dengan subquery; ini sangat lambat.Hanya digunakan
IN
dengan daftar nilai yang pasti.Lebih banyak tips
SELECT *
hanya pilih bidang yang benar-benar Anda butuhkan.relevant_field
untuk mempercepat equi-gabung.group by
menggunakan kunci utama.Solusi umum untuk 90% dari
IN (select
pertanyaan AndaGunakan kode ini
sumber
HAVING COUNT(*) > 1
. Biasanya lebih cepat di MySQL.st2.relevant_field
tidakNULL
(sudah termasuk dalamON
klausa), itu tidak akan mengubah hasilnyaafield
tidak akan pernahnull
, mengerti. Terima kasihgroup by
aktifst1.id
, bukan aktifst1.relevant_field
.Subquery dijalankan untuk setiap baris karena merupakan kueri yang dikorelasikan. Seseorang dapat membuat kueri terkorelasi menjadi kueri yang tidak berkorelasi dengan memilih segala sesuatu dari subquery, seperti:
Kueri akhir akan terlihat seperti ini:
sumber
SELECT *
pembungkus ini diperlukan.Subqueries vs joins
http://www.scribd.com/doc/2546837/New-Subquery-Optimizations-In-MySQL-6
sumber
Saya telah mencoba kueri Anda di salah satu basis data saya, dan juga mencobanya ditulis ulang sebagai bergabung ke sub-kueri.
Ini bekerja jauh lebih cepat, coba!
sumber
Coba ini
sumber
Saya telah memformat ulang permintaan sql Anda yang lambat dengan www.prettysql.net
Saat menggunakan tabel di kueri dan subquery, Anda harus selalu alias keduanya, seperti ini:
Apakah itu membantu?
sumber
Pertama, Anda dapat menemukan baris duplikat dan menemukan jumlah baris digunakan berapa kali dan memesannya dengan nomor seperti ini;
setelah itu buat tabel dan masukkan hasilnya.
Akhirnya, hapus baris dublicate. Tidak ada mulai 0. Kecuali nomor pertama dari setiap grup hapus semua baris dublicate.
sumber
kadang-kadang ketika data tumbuh lebih besar mysql WHERE IN bisa sangat lambat karena optimasi kueri. Coba gunakan STRAIGHT_JOIN untuk memberi tahu mysql untuk mengeksekusi kueri apa adanya, misalnya
tetapi waspadalah: dalam kebanyakan kasus pengoptimal mysql bekerja dengan sangat baik, jadi saya akan merekomendasikan untuk menggunakannya hanya ketika Anda memiliki masalah seperti ini
sumber
Ini mirip dengan kasus saya, di mana saya memiliki tabel bernama
tabel_buku_besar
. Yang saya butuhkan adalahMencari record yang memiliki
account_code='101.100'
ditabel_buku_besar
mana telahcompanyarea='20000'
dan juga memilikiIDR
sebagaicurrency
Saya perlu mendapatkan semua catatan
tabel_buku_besar
yang memiliki kode akun sama dengan langkah 1 tetapi adatransaction_number
dalam langkah 1 hasilsaat menggunakan
select ... from...where....transaction_number in (select transaction_number from ....)
, permintaan saya berjalan sangat lambat dan kadang-kadang menyebabkan waktu permintaan habis atau membuat aplikasi saya tidak menanggapi ...Saya mencoba kombinasi ini dan hasilnya ... tidak buruk ...
sumber
Saya menemukan ini menjadi yang paling efisien untuk menemukan jika ada nilai, logika dapat dengan mudah dibalik untuk menemukan jika nilai tidak ada (yaitu IS NULL);
* Ganti relevan_field dengan nama nilai yang ingin Anda periksa ada di tabel Anda
* Ganti primaryKey dengan nama kolom kunci utama pada tabel perbandingan.
sumber