Bottom line : การเพิ่มเกณฑ์ไปยังส่วนWHERE
คำสั่งและแยกแบบสอบถามเป็นสี่แบบสอบถามแยกต่างหากหนึ่งรายการสำหรับแต่ละเขตข้อมูลอนุญาตให้เซิร์ฟเวอร์ SQL จัดทำแผนคู่ขนานและทำให้แบบสอบถามเรียกใช้ 4X เร็วเท่าที่มีโดยไม่ต้องทดสอบเพิ่มเติมในWHERE
ข้อ การแบ่งคำถามออกเป็นสี่ข้อโดยไม่ต้องทำการทดสอบไม่ได้ทำเช่นนั้น ไม่มีการเพิ่มการทดสอบโดยไม่แยกแบบสอบถาม การเพิ่มประสิทธิภาพการทดสอบลดเวลาการทำงานทั้งหมดเป็น 3 นาที (จากเดิม 3 ชั่วโมง)
UDF ดั้งเดิมของฉันใช้เวลา 3 ชั่วโมง 16 นาทีในการประมวลผล 1,174,731 แถวโดยทดสอบข้อมูล nvarchar 1.216 GB การใช้ CLR ที่มาร์ตินสมิ ธ ให้ไว้ในคำตอบของเขาแผนปฏิบัติการยังไม่ขนานกันและใช้เวลา 3 ชั่วโมง 5 นาที
เมื่ออ่านแล้วว่าWHERE
เกณฑ์สามารถช่วยผลักดันUPDATE
ให้ขนานฉันทำต่อไปนี้ ฉันได้เพิ่มฟังก์ชั่นในโมดูล CLR เพื่อดูว่าเขตข้อมูลมีการจับคู่กับ regex หรือไม่:
[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());
}
และในinternal class ReplaceSpecification
ฉันเพิ่มรหัสเพื่อดำเนินการทดสอบกับ regex
internal bool IsMatch(string inputString)
{
if (Regex == null)
return false;
return Regex.IsMatch(inputString);
}
ถ้าเขตข้อมูลทั้งหมดจะถูกทดสอบในคำสั่งเดียวเซิร์ฟเวอร์ SQL ไม่ขนานงาน
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 ชั่วโมงและยังคงทำงานอยู่ แผนการดำเนินการ:
อย่างไรก็ตามถ้าเขตข้อมูลถูกแยกออกเป็นงบแยกมีการใช้แผนการทำงานแบบขนานและการใช้งาน CPU ของฉันเพิ่มขึ้นจาก 12% เมื่อใช้แผนอนุกรมเป็น 100% โดยใช้แผนขนาน (8 แกน)
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 นาที สถิติแถวแสดงให้เห็นว่าประมาณ 0.5% ของระเบียนมีการจับคู่ regex อย่างน้อยหนึ่งรายการ แผนการดำเนินการ:
ตอนนี้การลากหลักตรงเวลาคือWHERE
ข้อ ฉันแทนที่การทดสอบ regex ในWHERE
clause ด้วยอัลกอริทึม Aho-Corasick ที่ใช้เป็น CLR เวลาทั้งหมดนี้ลดลงเป็น 3 นาที 6 วินาที
ต้องมีการเปลี่ยนแปลงต่อไปนี้ โหลดชุดประกอบและฟังก์ชั่นสำหรับอัลกอริทึม Aho-Corasick เปลี่ยนWHERE
ข้อเป็น
WHERE InProcess = 1 AND dbo.ContainsWordsByObject(ISNULL(FieldBeingTestedGoesHere,'x'), @ac) = 1;
และเพิ่มรายการต่อไปนี้ก่อน 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
ก่อสร้างไม่รับประกันว่าจะทำงานตามที่คุณคาดหวัง ตัวอย่างรายการเชื่อมต่อ (ดูการตอบสนองจาก Microsoft) ดังนั้นการเปลี่ยนมาใช้ SQLCLR มีข้อดีเพิ่มเติมของการรับประกันผลลัพธ์ที่ถูกต้องซึ่งเป็นสิ่งที่ดีเสมอ