Saya mencoba meningkatkan kinerja kueri berikut:
UPDATE [#TempTable]
SET Received = r.Number
FROM [#TempTable]
INNER JOIN (SELECT AgentID,
RuleID,
COUNT(DISTINCT (GroupId)) Number
FROM [#TempTable]
WHERE Passed = 1
GROUP BY AgentID,
RuleID
) r ON r.RuleID = [#TempTable].RuleID AND
r.AgentID = [#TempTable].AgentID
Saat ini dengan data pengujian saya, dibutuhkan sekitar satu menit. Saya memiliki sejumlah input terbatas pada perubahan pada seluruh prosedur tersimpan di mana kueri ini berada, tetapi saya mungkin bisa meminta mereka untuk memodifikasi kueri yang satu ini. Atau tambahkan indeks. Saya mencoba menambahkan indeks berikut:
CREATE CLUSTERED INDEX ix_test ON #TempTable(AgentID, RuleId, GroupId, Passed)
Dan itu sebenarnya menggandakan jumlah waktu yang dibutuhkan kueri. Saya mendapatkan efek yang sama dengan indeks NON-CLUSTERED.
Saya mencoba menulis ulang sebagai berikut tanpa efek.
WITH r AS (SELECT AgentID,
RuleID,
COUNT(DISTINCT (GroupId)) Number
FROM [#TempTable]
WHERE Passed = 1
GROUP BY AgentID,
RuleID
)
UPDATE [#TempTable]
SET Received = r.Number
FROM [#TempTable]
INNER JOIN r
ON r.RuleID = [#TempTable].RuleID AND
r.AgentID = [#TempTable].AgentID
Selanjutnya saya mencoba menggunakan fungsi windowing seperti ini.
UPDATE [#TempTable]
SET Received = COUNT(DISTINCT (CASE WHEN Passed=1 THEN GroupId ELSE NULL END))
OVER (PARTITION BY AgentId, RuleId)
FROM [#TempTable]
Pada titik ini saya mulai mendapatkan kesalahan
Msg 102, Level 15, State 1, Line 2
Incorrect syntax near 'distinct'.
Jadi saya punya dua pertanyaan. Pertama, bisakah Anda tidak melakukan COUNT DISTINCT dengan klausa OVER atau apakah saya salah menuliskannya? Dan kedua, adakah yang bisa menyarankan perbaikan yang belum pernah saya coba? FYI ini adalah contoh SQL Server 2008 R2 Enterprise.
EDIT: Berikut ini tautan ke rencana eksekusi asli. Saya juga harus mencatat bahwa masalah besar saya adalah bahwa kueri ini dijalankan 30-50 kali.
https://onedrive.live.com/redir?resid=4C359AF42063BD98%21772
EDIT2: Berikut ini adalah loop penuh pernyataan itu seperti yang diminta dalam komentar. Saya memeriksa dengan orang yang bekerja dengan ini secara teratur untuk tujuan loop.
DECLARE @Counting INT
SELECT @Counting = 1
-- BEGIN: Cascading Rule check --
WHILE @Counting <= 30
BEGIN
UPDATE w1
SET Passed = 1
FROM [#TempTable] w1,
[#TempTable] w3
WHERE w3.AgentID = w1.AgentID AND
w3.RuleID = w1.CascadeRuleID AND
w3.RulePassed = 1 AND
w1.Passed = 0 AND
w1.NotFlag = 0
UPDATE w1
SET Passed = 1
FROM [#TempTable] w1,
[#TempTable] w3
WHERE w3.AgentID = w1.AgentID AND
w3.RuleID = w1.CascadeRuleID AND
w3.RulePassed = 0 AND
w1.Passed = 0 AND
w1.NotFlag = 1
UPDATE [#TempTable]
SET Received = r.Number
FROM [#TempTable]
INNER JOIN (SELECT AgentID,
RuleID,
COUNT(DISTINCT (GroupID)) Number
FROM [#TempTable]
WHERE Passed = 1
GROUP BY AgentID,
RuleID
) r ON r.RuleID = [#TempTable].RuleID AND
r.AgentID = [#TempTable].AgentID
UPDATE [#TempTable]
SET RulePassed = 1
WHERE TotalNeeded = Received
SELECT @Counting = @Counting + 1
END
count
jika kolom tersebut dapat dibatalkan. Jika mengandung nol, Anda harus mengurangi 1.