ในขณะทำโปรไฟล์ฐานข้อมูลฉันพบว่ามีการอ้างอิงฟังก์ชั่นที่ไม่ได้กำหนดค่าบางอย่างที่เข้าถึง1,000-2500 ครั้งต่อนาทีสำหรับการเชื่อมต่อแต่ละครั้งในแอพพลิเคชั่นนี้ วิSELECT
จากมุมมองทำให้แผนการดำเนินการต่อไปนี้:
ดูเหมือนว่าแผนซับซ้อนสำหรับมุมมองที่มีน้อยกว่าหนึ่งพันแถวที่อาจเห็นการเปลี่ยนแปลงหนึ่งหรือสองแถวทุกสองสามเดือน แต่มันก็แย่ลงด้วยการปฏิบัติอื่น ๆ ดังต่อไปนี้:
- มุมมองแบบซ้อนไม่สามารถกำหนดค่าได้ดังนั้นเราจึงไม่สามารถจัดทำดัชนีได้
- แต่ละมุมมองอ้างอิงหลาย
UDF
s เพื่อสร้างสตริง - UDF แต่ละอันประกอบด้วย
UDF
s ที่ซ้อนกันเพื่อรับรหัส ISO สำหรับภาษาที่แปลเป็นภาษาท้องถิ่น - ผู้ชมในกองกำลังใช้เพิ่มเติมสร้างสตริงกลับมาจาก
UDF
การเป็นJOIN
ภาค - มุมมองสแต็กแต่ละครั้งจะถือว่าเป็นตารางหมายความว่ามี
INSERT
/UPDATE
/DELETE
ทริกเกอร์ในแต่ละเพื่อเขียนไปยังตารางพื้นฐาน - ทริกเกอร์เหล่านี้ในมุมมองใช้
CURSORS
ว่าEXEC
วิธีการจัดเก็บที่อ้างอิงมากกว่านี้สตริงสร้างUDF
s
ดูเหมือนว่าฉันจะเน่าเสีย แต่ฉันมีประสบการณ์กับ TSQL เพียงไม่กี่ปี มันจะดีขึ้นเช่นกัน!
ดูเหมือนนักพัฒนาที่ตัดสินใจว่านี่เป็นความคิดที่ยอดเยี่ยมทำทั้งหมดนี้เพื่อให้สตริงสองสามร้อยรายการที่เก็บไว้สามารถมีการแปลตามสตริงที่ส่งคืนจากสตริงUDF
นั้นเป็นแบบเฉพาะสคีมา
นี่คือหนึ่งในมุมมองในสแต็ก แต่ทั้งหมดนั้นไม่ดีเท่ากัน:
CREATE VIEW [UserWKStringI18N]
AS
SELECT b.WKType, b.WKIndex
, CASE
WHEN ISNULL(il.I18NID, N'') = N''
THEN id.I18NString
ELSE il.I18nString
END AS WKString
,CASE
WHEN ISNULL(il.I18NID, N'') = N''
THEN id.IETFLangCode
ELSE il.IETFLangCode
END AS IETFLangCode
,dbo.User3StringI18N_KeyValue(b.WKType, b.WKIndex, N'WKS') AS I18NID
,dbo.UserI18N_Session_Locale_Key() AS IETFSessionLangCode
,dbo.UserI18N_Database_Locale_Key() AS IETFDatabaseLangCode
FROM UserWKStringBASE b
LEFT OUTER JOIN User3StringI18N il
ON (
il.I18NID = dbo.User3StringI18N_KeyValue(b.WKType, b.WKIndex, N'WKS')
AND il.IETFLangCode = dbo.UserI18N_Session_Locale_Key()
)
LEFT OUTER JOIN User3StringI18N id
ON (
id.I18NID = dbo.User3StringI18N_KeyValue(b.WKType, b.WKIndex,N'WKS')
AND id.IETFLangCode = dbo.UserI18N_Database_Locale_Key()
)
GO
นี่คือเหตุผลที่UDF
s ถูกใช้เป็นเพJOIN
รดิเคต I18NID
คอลัมน์จะเกิดขึ้นโดยเชื่อมโยง:STRING + [ + ID + | + ID + ]
ในระหว่างการทดสอบเหล่านี้ง่าย ๆSELECT
จากมุมมองส่งกลับ ~ 309 แถวและใช้เวลา 900-1400ms เพื่อดำเนินการ ถ้าฉันดัมพ์สตริงลงในตารางอื่นและตบดัชนีบนมันการเลือกเดียวกันจะส่งคืนภายใน 20-75ms
เรื่องสั้นสั้น ๆ (และฉันหวังว่าคุณจะพอใจกับความโง่เขลานี้) ฉันอยากเป็นชาวสะมาเรียที่ดีและออกแบบใหม่และเขียนสิ่งนี้ใหม่สำหรับลูกค้า 99% ที่ใช้ผลิตภัณฑ์นี้ซึ่งไม่ได้ใช้การแปลภาษาเลย - ผู้ใช้ระดับปลายคาดว่าจะใช้[en-US]
ภาษาแม้ในภาษาอังกฤษเป็นภาษาที่ 2/3
เนื่องจากนี่เป็นการแฮ็คอย่างไม่เป็นทางการฉันจึงคิดถึงสิ่งต่อไปนี้:
- สร้างตาราง String ใหม่ที่มีชุดข้อมูลที่เข้าร่วมอย่างเรียบร้อยจากตารางฐานดั้งเดิม
- จัดทำดัชนีตาราง
- สร้างชุดการแทนที่ของมุมมองระดับบนสุดในสแต็กที่รวม
NVARCHAR
และINT
คอลัมน์สำหรับWKType
และWKIndex
คอลัมน์ - ปรับเปลี่ยนจำนวน
UDF
เล็กน้อยที่อ้างอิงมุมมองเหล่านี้เพื่อหลีกเลี่ยงการแปลงประเภทในภาคแสดงร่วม (ตารางตรวจสอบที่ใหญ่ที่สุดของเราคือ 500-2,000 ล้านแถวและเก็บINT
ไว้ในNVARCHAR(4000)
คอลัมน์ที่ใช้เพื่อเข้าร่วมกับWKIndex
คอลัมน์ (INT
)) - วางแผนมุมมอง
- เพิ่มดัชนีบางอย่างในมุมมอง
- สร้างทริกเกอร์ในมุมมองอีกครั้งโดยใช้ set ตรรกะแทนเคอร์เซอร์
ตอนนี้คำถามจริงของฉัน:
- มีวิธีปฏิบัติที่ดีที่สุดในการจัดการสตริงที่แปลผ่านมุมมองหรือไม่?
- มีทางเลือกใด
UDF
บ้างสำหรับใช้เป็นสตับ (ฉันสามารถเขียนข้อมูลเฉพาะVIEW
สำหรับเจ้าของสคีมาแต่ละภาษาและเขียนโค้ดภาษายาก ๆ แทนที่จะพึ่งพาสUDF
ตับที่หลากหลาย) - มุมมองเหล่านี้สามารถกำหนดได้ง่าย ๆ โดยการคัดเลือก
UDF
s ที่ซ้อนกันทั้งหมดแล้วจึงวางแผนดูสแต็ก?
UDF
คำจำกัดความของคุณเช่นกัน นอกจากนี้อ้างถึงฟังก์ชั่นที่ผู้ใช้กำหนดเองของ T-SQL: ข้อดีข้อเสียและน่าเกลียด