SQL server 2008 R2 query optimizer puzzle
Kami memiliki dua tabel, keduanya berisi 9 juta baris. 70.000 baris berbeda, yang lain sama.
Ini cepat, 13 detik,
select * from bigtable1
except select * from similar_bigtable2
Ini memilah output dan juga cepat, 13 detik juga,
select * into #q from bigtable1
except select * from similar_bigtable2
select * from #q order by sort_column
Meskipun ini sangat lambat:
;with q as (
select * from bigtable1
except select * from similar_bigtable2
)
select * from q order by sort_column
Dan bahkan "trik" yang kadang-kadang saya gunakan untuk mengisyaratkan SQL Server bahwa ia perlu menghitung ulang bagian tertentu dari kueri sebelum melanjutkan, tidak berfungsi dan menghasilkan kueri lambat juga:
;with q as (
select top 100 percent * from bigtable1
except select * from similar_bigtable2
)
select * from q order by sort_column
Melihat rencana kueri alasannya tidak sulit ditemukan:
SQL Server menempatkan dua jenis 9 juta baris sebelum hashmatch, sementara saya lebih suka untuk menambahkan hanya satu jenis 70.000 baris setelah hashmatch.
Jadi pertanyaannya: bagaimana saya bisa memerintahkan pengoptimal kueri untuk melakukan itu?
sql-server
sql-server-2008
thomaspaulb
sumber
sumber
EXCEPT
(misalnyaOUTER JOIN
)? Saya menyadari sintaksnya kurang nyaman tetapi Anda mungkin dapat bermain dengan petunjuk indeks / bergabung lebih baik di sana (atau Anda mungkin tidak perlu). Alternatif yang Anda gunakan sekarang (memasukkan item ke tabel #temp terlebih dahulu) adalah solusi terakhir tetapi dalam beberapa kasus adalah satu-satunya cara untuk memaksa pengoptimal untuk sepenuhnya memisahkan dua bagian dari kueri dengan cara yang Anda inginkan.Jawaban:
Perbedaan utama antara kedua paket kueri ini sebenarnya dalam perbedaan Hash Match dan Gabung Bergabung. Pencocokan Hash lebih efisien dan karena Anda dapat melihat kueri berjalan lebih cepat di opsi 1 (tidak menggunakan CTE).
CTE adalah alat yang hebat, tetapi tampaknya tidak efisien dalam dua kasus, Predikat Kompleks atau Kunci Induk / Anak yang Tidak Unik. Dalam kasus Anda tidak ada kunci unik dan SQL server harus mengurutkan set data terlebih dahulu untuk dapat memenuhi kebutuhan Anda. Lihat tautan di bawah ini yang memberi tahu Anda lebih banyak tentang masalah ini: http://blogs.msdn.com/b/sqlcat/archive/2011/04/28/optimize-recursive-cte-query.aspx
Jadi sepertinya Anda harus menerima kelambatannya atau menulis ulang logikanya dengan WHILE loop yang bisa lebih efisien.
sumber
Coba ini, lebih baik?
sumber
Ini bukan solusi yang ideal tetapi jika Anda tidak dapat menyusun tsql untuk menghasilkan rencana yang efisien, Anda dapat menetapkan panduan rencana untuk memaksa rencana yang Anda inginkan. Melakukan ini akan berarti bahwa jika rencana yang lebih efisien tersedia, SQL tidak akan mempertimbangkannya tetapi itu adalah pilihan.
sumber