Alt satır : Cümleye ölçüt ekleme WHERE
ve sorguyu dört ayrı sorguya bölme, her alan için bir tane SQL sunucusunun paralel bir plan sağlamasına izin verdi ve sorguyu, WHERE
yan tümcede fazladan test yapılmadan 4X kadar hızlı çalıştırdı . Test olmadan sorguları dörde bölmek bunu yapmadı. Sorguları bölmeden testi de eklemedi. Testin optimize edilmesi toplam çalışma süresini 3 dakikaya düşürdü (orijinalden 3 saat).
Orijinal UDF'm, 1.216 GB nvarchar verisi test edilerek 1.174.731 satırı işlemek için 3 saat 16 dakika sürdü. Cevabında Martin Smith tarafından sağlanan CLR'yi kullanarak yürütme planı hala paralel değildi ve görev 3 saat 5 dakika sürdü.
Bu WHERE
kriterleri okuduktan sonra, a'yı UPDATE
paralel hale getirmeye yardımcı olabilir , aşağıdakileri yaptım. Alanın normal ifadeyle eşleşip eşleşmediğini görmek için CLR modülüne bir işlev ekledim:
[SqlFunction(IsDeterministic = true,
IsPrecise = true,
DataAccess = DataAccessKind.None,
SystemDataAccess = SystemDataAccessKind.None)]
public static SqlBoolean CanReplaceMultiWord(SqlString inputString, SqlXml replacementSpec)
{
string s = replacementSpec.Value;
ReplaceSpecification rs;
if (!cachedSpecs.TryGetValue(s, out rs))
{
var doc = new XmlDocument();
doc.LoadXml(s);
rs = new ReplaceSpecification(doc);
cachedSpecs[s] = rs;
}
return rs.IsMatch(inputString.ToString());
}
ve internal class ReplaceSpecification
regex'e karşı testi yürütmek için kod ekledim
internal bool IsMatch(string inputString)
{
if (Regex == null)
return false;
return Regex.IsMatch(inputString);
}
Tüm alanlar tek bir ifadede test edilirse, SQL sunucusu çalışmayı paralelleştirmez
UPDATE dbo.DeidentifiedTest
SET IndexedXml = dbo.ReplaceMultiWord(IndexedXml, @X),
DE461 = dbo.ReplaceMultiWord(DE461, @X),
DE87 = dbo.ReplaceMultiWord(DE87, @X),
DE15 = dbo.ReplaceMultiWord(DE15, @X)
WHERE InProcess = 1
AND (dbo.CanReplaceMultiWord(IndexedXml, @X) = 1
OR DE15 = dbo.ReplaceMultiWord(DE15, @X)
OR dbo.CanReplaceMultiWord(DE87, @X) = 1
OR dbo.CanReplaceMultiWord(DE15, @X) = 1);
4 1/2 saatin üzerinde çalışma ve hala çalışıyor. Yürütme planı:
Ancak, alanlar ayrı ifadelere ayrılırsa, paralel bir çalışma planı kullanılır ve CPU kullanımım seri planlarla% 12'den paralel planlarla (8 çekirdek)% 100'e gider.
UPDATE dbo.DeidentifiedTest
SET IndexedXml = dbo.ReplaceMultiWord(IndexedXml, @X)
WHERE InProcess = 1
AND dbo.CanReplaceMultiWord(IndexedXml, @X) = 1;
UPDATE dbo.DeidentifiedTest
SET DE461 = dbo.ReplaceMultiWord(DE461, @X)
WHERE InProcess = 1
AND dbo.CanReplaceMultiWord(DE461, @X) = 1;
UPDATE dbo.DeidentifiedTest
SET DE87 = dbo.ReplaceMultiWord(DE87, @X)
WHERE InProcess = 1
AND dbo.CanReplaceMultiWord(DE87, @X) = 1;
UPDATE dbo.DeidentifiedTest
SET DE15 = dbo.ReplaceMultiWord(DE15, @X)
WHERE InProcess = 1
AND dbo.CanReplaceMultiWord(DE15, @X) = 1;
46 dakika çalışma süresi. Sıra istatistikleri, kayıtların yaklaşık% 0.5'inin en az bir normal ifade eşleşmesine sahip olduğunu gösterdi. Yürütme planı:
Şimdi, zamanın ana sürüklemesi WHERE
maddeydi. Daha sonra, cümledeki normal ifade testini CLR olarak uygulanan Aho-Corasick algoritmasıWHERE
ile değiştirdim . Bu toplam süreyi 3 dakika 6 saniyeye düşürdü.
Bu, aşağıdaki değişiklikleri gerektiriyordu. Aho-Corasick algoritması için montaj ve fonksiyonları yükleyin. Yan WHERE
tümcesi olarak değiştirin
WHERE InProcess = 1 AND dbo.ContainsWordsByObject(ISNULL(FieldBeingTestedGoesHere,'x'), @ac) = 1;
Ve ilk önce aşağıdakileri ekleyin UPDATE
DECLARE @ac NVARCHAR(32);
SET @ac = dbo.CreateAhoCorasick(
(SELECT NAMES FROM dbo.NamesMultiWord FOR XML RAW, root('root')),
'en-us:i'
);
SELECT @var = REPLACE ... ORDER BY
beklediğiniz gibi çalışacağı garanti edilmez. Örnek Connect öğesi (Microsoft'un yanıtına bakın). Bu nedenle, SQLCLR'ye geçmek, her zaman iyi olan doğru sonuçları garanti etmenin ek avantajına sahiptir.