Ini adalah pemilihan sederhana dari tabel sementara, kiri bergabung dengan tabel yang ada pada kunci utama, dengan dua sub memilih menggunakan top 1 merujuk tabel bergabung.
Dalam kode:
SELECT
TempTable.Col1,
TempTable.Col2,
TempTable.Col3,
JoinedTable.Col1,
JoinedTable.Col2,
(
SELECT TOP 1
ThirdTable.Col1 -- Which is ThirdTable's Primary Key
FROM
ThirdTable
WHERE
ThirdTable.SomeColumn = JoinedTable.SomeColumn
) as ThirdTableColumn1,
(
SELECT TOP 1
ThirdTable.Col1 -- Which is also ThirdTable's Primary Key
FROM
ThirdTable
WHERE
ThirdTable.SomeOtherColumn = JoinedTable.SomeColumn
) as ThirdTableColumn2,
FROM
#TempTable as TempTable
LEFT JOIN
JoinedTable
ON (TempTable.PKColumn1 = JoinedTable.PKColumn1 AND
TempTable.PKColumn2 = JoinedTable.PKColumn2)
WHERE
JoinedTable.WhereColumn IN (1, 3)
Ini adalah replika persis dari kueri saya.
Jika saya menghapus dua sub seleksi, itu berjalan dengan baik dan cepat. Dengan dua sub pilihan, saya mendapatkan sekitar 100 catatan per detik, yang sangat lambat untuk kueri ini karena harus mengembalikan hampir satu juta catatan.
Saya telah memeriksa untuk melihat apakah setiap tabel memiliki Kunci Utama, semuanya memiliki. Mereka semua memiliki Indeks DAN statistik untuk kolom penting mereka, seperti yang ada di klausa WHERE itu, dan yang ada di klausa GABUNG. Satu-satunya tabel tanpa kunci primer yang ditentukan atau indeks adalah tabel sementara, tetapi itu bukan masalah juga karena itu bukan yang terkait dengan subseleksi yang lambat, dan seperti yang saya sebutkan, tanpa sub seleksi itu berjalan dengan baik.
Tanpa yang TOP 1
mengembalikan lebih dari satu hasil, dan menimbulkan kesalahan.
Tolong, tolong siapa?
EDIT :
Jadi rencana eksekusi memberitahuku bahwa aku kehilangan Indeks. Saya telah membuatnya, dan menciptakan kembali beberapa indeks lainnya. Setelah beberapa saat, rencana eksekusi menggunakannya, dan permintaan sekarang berjalan cepat. Satu-satunya masalah adalah saya tidak berhasil melakukan ini lagi di server lain, untuk permintaan yang sama. Jadi solusi saya akan ke PETUNJUK indeks SQL Server yang akan digunakan.
Jawaban:
Saya pikir dalam sejuta catatan kueri, Anda harus menghindari hal-hal seperti
OUTER JOINS
. Saya sarankan Anda menggunakanUNION ALL
Alih-alihLEFT JOIN
. Selama saya pikirCROSS APPLY
lebih efisien daripada sub-kueri dalam klausa pilih, saya akan memodifikasi kueri yang ditulis oleh Conard Frix, yang menurut saya benar.sekarang: ketika saya mulai memodifikasi query Anda saya melihat bahwa Anda memiliki klausa WHERE mengatakan:
JoinedTable.WhereColumn IN (1, 3)
. dalam hal ini, jika bidangnya nol maka kondisinya akan menjadi salah. lalu mengapa Anda menggunakan LEFT JOIN saat Anda memfilter baris bernilai nol? cukup gantiLEFT JOIN
DenganINNER JOIN
, saya jamin itu akan menjadi lebih cepat.tentang INDEX:
harap dicatat bahwa ketika Anda memiliki indeks di atas meja, katakanlah
dan indeks Anda adalah:
dan Anda ingin melakukan sesuatu seperti ini:
dalam indeks Anda, Anda belum memasukkan kolom
b
jadi apa yang terjadi?jika sql-server menggunakan indeks Anda, itu harus mencari dalam indeks, yang disebut "Indeks Mencari" dan kemudian merujuk ke tabel utama untuk mendapatkan kolom
b
, yang disebut "Mencari" . Prosedur ini mungkin memakan waktu lebih lama daripada memindai tabel itu sendiri: "Pemindaian Tabel" .tetapi berdasarkan statistik yang dimiliki sql-server, dalam situasi seperti itu, mungkin tidak menggunakan indeks Anda sama sekali.
jadi pertama-tama periksa
Execution Plan
untuk melihat apakah indeks digunakan sama sekali.jika ya atau tidak keduanya, ubah indeks Anda untuk memasukkan semua kolom yang Anda pilih. katakan seperti:
dalam hal ini Look Up tidak diperlukan, dan permintaan Anda akan dieksekusi jauh lebih cepat.
sumber
Subnya memilih dalam pemilihan kolom Anda yang menyebabkan pengembalian lambat. Anda harus mencoba menggunakan sub-pilihan Anda di gabungan kiri, atau menggunakan tabel turunan seperti yang telah saya tentukan di bawah.
Menggunakan Left Joins untuk dua contoh dari Third Table
Menggunakan Tabel Turunan
sumber
Coba beri tanda silang
Anda juga dapat menggunakan CTE dan row_number atau kueri inline menggunakan MIN
sumber
Pindahkan bit JOIN dari bagian utama klausa dan letakkan sebagai subselect. Memindahkannya ke bagian WHERE dan JOIN menjamin Anda tidak perlu SELECT TOP 1 berulang-ulang, yang saya percaya adalah alasan kelambatan hte. Jika Anda ingin memeriksa ini, periksa rencana eksekusi.
sumber
Itu
ThirdTable
referensi, (sub menyeleksi dalam contoh Anda), perlu indeks perhatian yang sama seperti bagian lain dari query.Terlepas dari apakah Anda menggunakan sub pilih:
LEFT BERGABUNG (seperti yang diusulkan oleh John Hartsock):
LINTAS BERLAKU (seperti yang diusulkan oleh Conrad Frix):
Anda perlu memastikan
covering indexes
untuk didefinisikanThirdTable.SomeColumn
danThirdTable.SomeOtherColumn
dan indeks unik. Ini berarti Anda perlu lebih lanjut memenuhi syaratThirdTable
referensi untuk menghilangkan pemilihan beberapa baris dan meningkatkan kinerja. Pilihansub selects
,LEFT JOIN
atauCROSS APPLY
tidak akan benar-benar peduli sampai Anda meningkatkan selektivitas untukThirdTable.SomeColumn
danThirdTable.SomeOtherColumn
oleh termasuk lebih kolom untuk memastikan selektivitas yang unik. Sampai saat itu, saya berharap kinerja Anda akan terus menderita.Itu
covering index
topik yang baik diperkenalkan oleh Maziar Taheri; sementara tidak mengulangi pekerjaannya, saya menekankan perlunya untuk mengambil hati menggunakan indeks yang meliputi.Singkatnya: Tingkatkan selektivitas untuk
ThirdTable.SomeColumn
danThirdTable.SomeOtherColumn
kueri (atau gabung ) dengan menambahkan kolom dalam-tabel terkait untuk memastikan kecocokan baris yang unik. Jika ini tidak memungkinkan, maka Anda akan terus mengalami masalah kinerja karena mesin sibuk menarik baris yang kemudian dibuang. Ini berdampak pada i / o, cpu, dan, akhirnya, rencana eksekusi Anda.sumber