Kami menjalankan situs web yang memiliki 250MM baris dalam satu tabel dan di tabel lain yang kami gabungkan untuk sebagian besar kueri yang memiliki hanya di bawah 15MM baris.
Struktur sampel:
MasterTable (Id, UserId, Created, Updated...) -- 15MM Rows
DetailsTable (Id, MasterId, SomeColumn...) -- 250MM Rows
UserTable (Id, Role, Created, UserName...) -- 12K Rows
Kami secara teratur harus melakukan beberapa pertanyaan terhadap semua tabel ini. Salah satunya adalah meraih statistik untuk pengguna gratis (~ 10k pengguna gratis).
Select Count(1) from DetailsTable dt
join MasterTable mt on mt.Id = dt.MasterId
join UserTable ut on ut.Id = mt.UserId
where ut.Role is null and mt.created between @date1 and @date2
Masalahnya adalah permintaan ini beberapa kali akan berjalan sangat lama karena fakta bahwa sambungan terjadi jauh sebelum di mana.
Dalam hal ini apakah akan lebih bijaksana untuk menggunakan where daripada join atau mungkin where column in(...)
?
join
best-practices
Jeremy Boyd
sumber
sumber
Jawaban:
Untuk RDBMS modern tidak ada perbedaan antara "JOIN eksplisit" dan "JOIN-in-the-WHERE" (jika semua JOIN adalah INNER) berkaitan dengan kinerja dan rencana kueri.
Sintaks JOIN eksplisit lebih jelas dan kurang ambigu (lihat tautan di bawah)
Sekarang, GABUNG-sebelum-DI MANA adalah pemrosesan logis, bukan pemrosesan aktual dan pengoptimal modern cukup pintar untuk menyadari hal ini.
Masalah Anda di sini kemungkinan besar adalah pengindeksan.
Tolong tunjukkan kami semua indeks dan kunci pada tabel ini. Dan rencana kueri
Catatan: pertanyaan ini akan ditutup pada StackOverflow karena menjadi duplikat sekarang ... COUNT (1) vs COUNT (*) juga merupakan mitos rusak lainnya.
sumber
join
danwhere
klausa. Saya mengoptimalkan kueri yang berjalan lama sepanjang waktu dan terkadang kueri yang menggunakanwhere
klausa berkinerja lebih baik daripada yang menggunakanjoin
faktor hingga 70x. Jika sesederhana dan semudah itu, hidup akan menjadi pelangi dan unicorn. Dan ini bukan tentang beberapa mesin tidak dikenal kuno - sekarang saya melihat 70x keuntungan dariwhere
klausa di SQL 2012.where
kueri klausa berjalan dalam batch besar itu seharusnya menjadi bagian dari, itu mengunggulijoin
kueri dengan margin besar. Query SQL tidak dieksekusi dalam ruang hampa - mereka dipengaruhi oleh sisa muatan server, dan seringkaliwhere
permintaan klausa berjalan dengan cukup baik, yang merupakan gangguan karenajoin
sintaks memang jauh lebih bersih.Anda harus mengubah permintaan secara bersamaan
Coba lakukan klausa WHERE sebelumnya dan GABUNG nanti
Bahkan jika Anda menjalankan paket EXPLAIN pada permintaan refactored ini dan terlihat lebih buruk dari aslinya, coba saja. Tabel temp yang dibuat secara internal akan melakukan penggabungan kartesian tetapi tabel tersebut lebih kecil untuk dikerjakan.
Saya mendapat ide ini dari video YouTube ini .
Saya mencoba prinsip-prinsip dari video dalam pertanyaan yang sangat kompleks di StackOverflow dan mendapat hadiah 200 poin.
@ GBN disebutkan memastikan Anda memiliki indeks yang tepat di tempat. Dalam hal ini, silakan indeks kolom yang dibuat di MasterTable.
Cobalah !!!
UPDATE 2011-06-24 22:31 EDT
Anda harus menjalankan kueri ini:
Jika NullRoles X 20 <AllRoles (dengan kata lain, jika NullRoles kurang dari 5% dari baris tabel), Anda harus membuat indeks non-unik Peran di UserTable. Jika tidak, tabel penuh UserTable akan cukup karena Pengoptimal Permintaan mungkin mengesampingkan penggunaan indeks.
UPDATE 2011-06-25 12:40 EDT
Karena saya seorang DBA MySQL, metode saya dalam melakukan sesuatu tidak perlu mempercayai MySQL Query Optimizer melalui pesimisme positif dan bersikap konservatif. Jadi, saya akan mencoba refactoring kueri atau membuat indeks yang diperlukan untuk mengatasi kebiasaan buruk tersembunyi MySQL Query Optimizer. @ gbn's jawaban tampaknya lebih lengkap karena SQL Server mungkin memiliki lebih banyak "kesehatan pikiran" mengevaluasi permintaan.
sumber
Kami memiliki tabel [Detail] tentang 75M baris; tabel [Master] sekitar 400K baris dan tabel [Item] terkait yang memiliki 7 baris - selalu dan selamanya. Ini menyimpan set kecil "Item number" (1-7) dan memodelkan bentuk kertas, jutaan di antaranya dicetak dan didistribusikan setiap bulan. Permintaan tercepat adalah yang paling tidak Anda pikirkan terlebih dahulu, yang melibatkan penggunaan Cartesian Join. IIRC, itu seperti:
Meskipun ada tautan “id” logis antara [Item] dan [Detail] CROSS JOIN bekerja lebih baik daripada INNER JOIN.
RDBMS adalah Teradata dengan teknologi MPP-nya, dan IDR apa skema pengindeksannya. Tabel 7 baris tidak memiliki indeks karena TABLE SCAN selalu melakukan yang terbaik.
sumber