it-swarm.asia

Apa yang lebih efisien, klausa mana atau gabungan dengan jutaan tabel baris plus?

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 wheres daripada bergabung atau mungkin where column in(...)?

20
Jeremy Boyd

Untuk RDBMS modern tidak ada perbedaan antara "JOIN eksplisit" dan "JOIN-in-the-WHERE" (jika semua JOIN adalah INNER) mengenai kinerja dan rencana kueri.

Sintaks JOIN eksplisit lebih jelas dan kurang ambigu (lihat tautan di bawah)

Sekarang, GABUNG-sebelum-DI MANA adalah logis sedang memproses tidak aktual sedang memproses 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.

20
gbn

Anda harus memperbaiki permintaan secara bersamaan

Coba lakukan klausa WHERE sebelumnya dan GABUNG nantinya

Select Count(1) from DetailsTable dt
join (Select UserId,Id FROM MasterTable where
created between @date1 and @date2) mt on mt.Id = dt.MasterId 
join (Select Id FROM UserTable WHERE Role is NULL) ut
on ut.Id = mt.UserId;

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:

SELECT COUNT(1) AllRoles FROM UserTable;
SELECT COUNT(1) NullRoles FROM UserTable WHERE Role is NULL;

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.

6
RolandoMySQLDBA

Kami memiliki tabel [Detail] tentang 75M baris; tabel [Master] sekitar 400K baris dan tabel [Item] terkait yang memiliki 7 baris - selalu dan selamanya. Itu 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:

SELECT m.order_id, i.line_nr, d.Item_amt
FROM Master m, Item i 
INNER JOIN Detail d ON m.order_id = d.order_id

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.

1
Timothy Oleary