Saya memiliki permintaan yang membutuhkan waktu sekitar 3 jam untuk berjalan di server kami - dan itu tidak memanfaatkan pemrosesan paralel. (sekitar 1,15 juta catatan masuk dbo.Deidentified
, 300 catatan masuk dbo.NamesMultiWord
). Server memiliki akses ke 8 core.
UPDATE dbo.Deidentified
WITH (TABLOCK)
SET IndexedXml = dbo.ReplaceMultiWord(IndexedXml),
DE461 = dbo.ReplaceMultiWord(DE461),
DE87 = dbo.ReplaceMultiWord(DE87),
DE15 = dbo.ReplaceMultiWord(DE15)
WHERE InProcess = 1;
dan ReplaceMultiword
merupakan prosedur yang didefinisikan sebagai:
SELECT @body = REPLACE(@body,Names,Replacement)
FROM dbo.NamesMultiWord
ORDER BY [WordLength] DESC
RETURN @body --NVARCHAR(MAX)
Apakah seruan untuk ReplaceMultiword
mencegah pembentukan rencana paralel? Apakah ada cara untuk menulis ulang ini untuk memungkinkan paralelisme?
ReplaceMultiword
berjalan dalam urutan menurun karena beberapa penggantian adalah versi pendek dari yang lain, dan saya ingin pertandingan terlama berhasil.
Misalnya, mungkin ada 'Universitas George Washington' dan yang lain dari 'Universitas Washington'. Jika pertandingan 'Universitas Washington' adalah yang pertama, maka 'George' akan tertinggal.
Secara teknis saya bisa menggunakan CLR, saya hanya tidak terbiasa dengan cara melakukannya.
SELECT @var = REPLACE ... ORDER BY
konstruksi tidak dijamin untuk bekerja seperti yang Anda harapkan. Contoh Sambungkan item (lihat respons dari Microsoft). Jadi, beralih ke SQLCLR memiliki keuntungan tambahan untuk menjamin hasil yang benar, yang selalu menyenangkan.Jawaban:
UDF mencegah paralelisme. Ini juga menyebabkan gulungan itu.
Anda bisa menggunakan CLR dan regex yang dikompilasi untuk melakukan pencarian dan penggantian. Itu tidak memblokir paralelisme selama atribut yang diperlukan ada dan kemungkinan akan secara signifikan lebih cepat daripada melakukan 300
REPLACE
operasi TSQL per panggilan fungsi.Contoh kode di bawah ini.
Ini tergantung pada keberadaan CLR UDF seperti di bawah ini (
DataAccessKind.None
seharusnya berarti spool menghilang serta ada untuk perlindungan Halloween dan tidak diperlukan karena ini tidak mengakses tabel target).sumber
where
klausa menggunakan tes untuk mencocokkan dengan regex, karena sebagian besar penulisan tidak perlu - kepadatan 'hit' harus rendah, tetapi keterampilan C # saya (saya seorang pria C ++) tidak bawa aku kesana Saya berpikir sepanjang baris prosedurpublic static SqlBoolean CanReplaceMultiWord(SqlString inputString, SqlXml replacementSpec)
yang akan kembalireturn Regex.IsMatch(inputString.ToString());
tetapi saya mendapatkan kesalahan pada pernyataan kembali itu, seperti `System.Text.RegularExpressions.Regex adalah tipe tetapi digunakan seperti variabel.Intinya : Menambahkan kriteria ke
WHERE
klausa dan memecah kueri menjadi empat kueri terpisah, satu untuk setiap bidang memungkinkan server SQL untuk menyediakan rencana paralel dan membuat kueri berjalan 4X secepat yang dimilikinya tanpa pengujian tambahan dalamWHERE
klausa. Memisahkan kueri menjadi empat tanpa tes tidak berhasil. Juga tidak menambahkan tes tanpa memecah pertanyaan. Mengoptimalkan tes mengurangi total waktu berjalan menjadi 3 menit (dari aslinya 3 jam).UDF asli saya memerlukan 3 jam 16 menit untuk memproses 1.174.731 baris, dengan 1.216 GB data nvarchar diuji. Menggunakan CLR yang disediakan oleh Martin Smith dalam jawabannya, rencana eksekusi masih tidak paralel dan tugasnya memakan waktu 3 jam dan 5 menit.
Setelah membaca bahwa
WHERE
kriteria dapat membantu mendorong suatuUPDATE
paralel, saya melakukan hal berikut. Saya menambahkan fungsi ke modul CLR untuk melihat apakah bidang tersebut cocok dengan regex:dan, dalam
internal class ReplaceSpecification
, saya menambahkan kode untuk menjalankan tes terhadap regexJika semua bidang diuji dalam satu pernyataan, SQL server tidak memparalelkan pekerjaan
Waktu untuk mengeksekusi lebih dari 4 1/2 jam dan masih berjalan. Rencana eksekusi:
Namun, jika bidang dipisahkan ke dalam pernyataan terpisah, rencana kerja paralel digunakan, dan penggunaan CPU saya beralih dari 12% dengan paket seri menjadi 100% dengan paket paralel (8 core).
Waktu untuk mengeksekusi 46 menit. Statistik baris menunjukkan bahwa sekitar 0,5% dari catatan memiliki setidaknya satu pertandingan regex. Rencana eksekusi:
Sekarang, hambatan utama tepat waktu adalah
WHERE
klausa. Saya kemudian mengganti tes regex dalamWHERE
klausa dengan algoritma Aho-Corasick diimplementasikan sebagai CLR. Ini mengurangi total waktu menjadi 3 menit 6 detik.Ini membutuhkan perubahan berikut. Memuat perakitan dan fungsi untuk algoritma Aho-Corasick. Ubah
WHERE
klausa menjadiDan tambahkan berikut ini sebelum yang pertama
UPDATE
sumber