Saya punya pemicu UPDATE di atas meja yang mengawasi kolom tertentu yang berubah dari satu nilai tertentu ke nilai lainnya. Ketika ini terjadi, itu memperbarui beberapa data terkait di tabel lain melalui pernyataan UPDATE tunggal.
Hal pertama yang dilakukan pemicu adalah memeriksa untuk melihat apakah ada baris yang diperbarui memiliki nilai kolom ini berubah dari nilai yang dimaksud. Ia hanya bergabung dengan INSERTED ke DELETED dan membandingkan nilai di kolom itu. Jika tidak ada yang memenuhi syarat, itu ditebus lebih awal sehingga pernyataan UPDATE tidak berjalan.
IF NOT EXISTS (
SELECT TOP 1 i.CUSTNMBR
FROM INSERTED i
INNER JOIN DELETED d
ON i.CUSTNMBR = d.CUSTNMBR
WHERE d.CUSTCLAS = 'Misc'
AND i.CUSTCLAS != 'Misc'
)
RETURN
Dalam hal ini, CUSTNMBR adalah kunci utama dari tabel yang mendasarinya. Jika saya melakukan pembaruan besar pada tabel ini (katakanlah, 5000+ baris), pernyataan ini membutuhkan AGES, bahkan jika saya belum menyentuh kolom CUSTCLAS. Saya bisa melihatnya berhenti pada pernyataan ini selama beberapa menit di Profiler.
Rencana eksekusi itu aneh. Ini menunjukkan Scan Dimasukkan dengan 3.714 eksekusi, dan ~ 18.5 juta baris output. Itu berjalan melalui filter pada kolom CUSTCLAS. Ini menggabungkan ini (melalui loop bersarang) ke Scan Dihapus (juga difilter pada CUSTCLAS), yang dieksekusi hanya sekali dan memiliki 5.000 baris output.
Apa hal bodoh yang saya lakukan di sini yang menyebabkan ini? Perhatikan bahwa pemicu harus benar-benar menangani pembaruan multi-baris.
EDIT :
Saya juga mencoba menulis seperti ini (kalau-kalau ada yang melakukan sesuatu yang tidak menyenangkan), tapi tetap saja mengerikan.
DECLARE @CUSTNMBR varchar(31)
SELECT TOP 1 @CUSTNMBR = i.CUSTNMBR
FROM INSERTED i
INNER JOIN DELETED d
ON i.CUSTNMBR = d.CUSTNMBR
WHERE d.CUSTCLAS = 'Misc'
AND i.CUSTCLAS != 'Misc'
IF @CUSTNMBR IS NULL
RETURN