Saya memiliki dua server basis data, terhubung melalui Server Tertaut. Keduanya adalah database SQL Server 2008R2, dan koneksi server tertaut dibuat melalui tautan "SQL Server" biasa, menggunakan konteks keamanan login saat ini. Server yang ditautkan keduanya berada di pusat data yang sama, sehingga koneksi tidak menjadi masalah.
Saya menggunakan kueri berikut untuk memeriksa nilai kolom mana identifier
yang tersedia dari jarak jauh, tetapi tidak secara lokal.
SELECT
identifier
FROM LinkedServer.RemoteDb.schema.[TableName]
EXCEPT
SELECT DISTINCT
identifier
FROM LocalDb.schema.[TableName]
Di kedua tabel adalah indeks non-cluster di kolom identifier
. Secara lokal sekitar 2,6 juta baris, hanya berjarak 54. Namun, ketika melihat rencana kueri, 70% dari waktu eksekusi dikhususkan untuk "mengeksekusi kueri jarak jauh". Juga, ketika mempelajari rencana kueri yang lengkap, jumlah baris lokal yang diestimasi 1
bukan 2695380
(yang merupakan jumlah baris yang diestimasikan ketika memilih hanya query yang datang setelahnya EXCEPT
).
Saat menjalankan kueri ini, memang butuh waktu lama.
Itu membuat saya bertanya-tanya: Mengapa ini? Apakah perkiraan "hanya" jauh, atau apakah pertanyaan jarak jauh pada server yang terhubung benar-benar mahal?
Jawaban:
Rencana yang Anda miliki saat ini terlihat seperti rencana paling optimal bagi saya.
Saya tidak setuju dengan pernyataan di jawaban lain bahwa ia mengirim baris 2.6M ke server jarak jauh.
Rencana itu terlihat bagi saya seolah-olah untuk masing-masing 54 baris yang dikembalikan dari permintaan jarak jauh itu melakukan pencarian indeks ke tabel lokal Anda untuk menentukan apakah cocok atau tidak. Ini adalah rencana optimal.
Mengganti dengan hash bergabung atau menggabungkan bergabung akan menjadi kontraproduktif mengingat ukuran tabel dan menambahkan
#temp
tabel perantara hanya menambahkan langkah tambahan yang tampaknya tidak memberi Anda keuntungan apa pun.sumber
Menghubungkan ke sumber daya jarak jauh mahal. Titik.
Salah satu operasi yang paling mahal di lingkungan pemrograman apa pun adalah IO jaringan (meskipun disk IO cenderung mengecilkannya).
Ini meluas ke server yang terhubung jauh. Server yang memanggil server yang terhubung jauh perlu terlebih dahulu membuat koneksi, kemudian permintaan harus dijalankan pada server jauh, hasilnya dikembalikan dan koneksi ditutup. Ini semua membutuhkan waktu melalui jaringan.
Anda juga harus menyusun kueri Anda sedemikian rupa sehingga Anda mentransfer data minimum melalui kawat. Jangan berharap DB akan mengoptimalkan untuk Anda.
Jika saya menulis kueri ini, saya akan memilih data jarak jauh menjadi variabel tabel (atau ke tabel temp) dan kemudian menggunakan ini dalam hubungannya dengan tabel lokal. Ini memastikan bahwa hanya data yang perlu ditransfer yang akan.
Kueri yang Anda jalankan dapat dengan mudah mengirim baris 2,6M ke server jarak jauh untuk memproses
EXCEPT
klausa.sumber
Saya bukan ahli tetapi jika Anda menggunakan Union, Kecuali, atau Intersect, Anda tidak harus menggunakan "Distinct". Bergantung pada nilai-nilai dari LocalDb.schema. [TableName], kinerja kueri dapat ditingkatkan.
sumber
Oded benar, masalah kinerja disebabkan oleh pengiriman baris 2.6M ke server jarak jauh Anda.
Untuk memperbaiki masalah ini, Anda dapat memaksa data jarak jauh (54 baris) dikirim kepada Anda dengan menggunakan temp atau di tabel memori.
Menggunakan tabel sementara
sumber
Saya pikir Anda lebih baik mereplikasi tabel jarak jauh ke server tempat Anda bertanya dan kemudian menjalankan semua SQL Anda secara lokal.
sumber