เพิ่ม 7/11ปัญหานี้เกิดจากการหยุดชะงักเนื่องจากการสแกนดัชนีระหว่าง MERGE JOIN ในกรณีนี้ธุรกรรมที่พยายามรับ S lock ในดัชนีทั้งหมดที่ตารางหลัก FK แต่ก่อนหน้านี้ธุรกรรมอื่นวาง X lock ไว้ในค่าคีย์ของดัชนี
ให้ฉันเริ่มต้นด้วยตัวอย่างเล็ก ๆ (ใช้ TSQL2012 DB จาก 70-461 cource):
CREATE TABLE [Sales].[Orders](
[orderid] [int] IDENTITY(1,1) NOT NULL,
[custid] [int] NULL,
[empid] [int] NOT NULL,
[shipperid] [int] NOT NULL,
... )
คอลัมน์[custid], [empid], [shipperid]
เป็นพารามิเตอร์ที่มีการเชื่อมโยงกัน[Sales].[Customers], [HR].[Employees], [Sales].[Shippers]
ตามลำดับ ในแต่ละกรณีเรามีดัชนีคลัสเตอร์ในคอลัมน์ที่อ้างถึงในตาราง parrent
ALTER TABLE [Sales].[Orders] WITH CHECK ADD CONSTRAINT [FK_Orders_Customers] FOREIGN KEY([custid]) REFERENCES [Sales].[Customers] ([custid])
ALTER TABLE [Sales].[Orders] WITH CHECK ADD CONSTRAINT [FK_Orders_Employees] FOREIGN KEY([empid]) REFERENCES [HR].[Employees] ([empid])
ALTER TABLE [Sales].[Orders] WITH CHECK ADD CONSTRAINT [FK_Orders_Shippers] FOREIGN KEY([shipperid])REFERENCES [Sales].[Shippers] ([shipperid])
ฉันกำลังพยายามไปINSERT [Sales].[Orders] SELECT ... FROM
ยังตารางอื่นที่เรียกว่า[Sales].[OrdersCache]
ซึ่งมีโครงสร้างเหมือนกับ[Sales].[Orders]
คีย์ต่างประเทศยกเว้น สิ่งสำคัญอีกอย่างที่อาจกล่าวถึงในตาราง[Sales].[OrdersCache]
คือดัชนีแบบคลัสเตอร์
CREATE CLUSTERED INDEX idx_c_OrdersCache ON Sales.OrdersCache ( custid, empid )
ตามที่คาดไว้เมื่อฉันพยายามแทรกข้อมูลปริมาณน้อย LOOP JOIN ทำงานได้ดีทำให้ดัชนีค้นหาคีย์ต่างประเทศ
ด้วยข้อมูลจำนวนมาก MERGE JOIN ถูกใช้โดยเครื่องมือเพิ่มประสิทธิภาพการสืบค้นเป็นวิธีที่มีประสิทธิภาพมากที่สุดในการรักษาคีย์ foregn ในแบบสอบถาม
และไม่มีอะไรเกี่ยวข้องกับมันยกเว้นการใช้ OPTION (LOOP JOIN) ในกรณีของเราด้วยปุ่มต่างประเทศหรือ INP LOOP JOIN ในกรณี JOIN อย่างชัดเจน
ด้านล่างนี้เป็นคำถามที่ฉันพยายามเรียกใช้ในสภาพแวดล้อมของฉัน:
INSERT Sales.Orders (
custid, empid, shipperid, ... )
SELECT custid, empid, 2, ...
FROM Sales.OrdersCache
เมื่อดูที่แผนเราจะเห็นว่ากุญแจทั้งสามที่ผ่านการตรวจสอบความถูกต้องกับ MERGE JOIN ไม่ใช่วิธีที่เหมาะสมสำหรับฉันเนื่องจากใช้ดัชนี INDEX พร้อมการล็อคดัชนีทั้งหมด
การใช้ OPTION (LOOP JOIN) ไม่เหมาะสมเนื่องจากมีค่าใช้จ่ายมากกว่าการรวม MERGE เกือบ 15% (ฉันคิดว่าการถดถอยจะยิ่งใหญ่ขึ้นเมื่อปริมาณข้อมูลเพิ่มขึ้น)
ในคำสั่ง SELECT คุณสามารถดูค่าเดียวสำหรับshipperid
แอตทริบิวต์สำหรับชุดที่แทรกทั้งหมด ในความคิดของฉันต้องมีวิธีที่จะทำให้ขั้นตอนการตรวจสอบความถูกต้องสำหรับชุดที่แทรกไว้เร็วขึ้นอย่างน้อยสำหรับแอตทริบิวต์ที่ไม่เปลี่ยนรูป สิ่งที่ต้องการ:
- ทำให้ LOOP JOIN, MERGE JOIN, HASH JOIN ถ้าเรามีเซตย่อยที่ไม่ได้กำหนดไว้สำหรับการตรวจสอบ JOIN
- หากมีเพียงค่าเดียวที่ชัดเจนของคอลัมน์ที่ตรวจสอบแล้วเราจะทำการตรวจสอบเพียงครั้งเดียว (INDEX SEEK)
มีรูปแบบทั่วไปที่จะข้ามสถานการณ์ข้างต้นโดยใช้โครงสร้างรหัสวัตถุ DDL เพิ่มเติมและอื่น ๆ ?
เพิ่ม 20/07 สารละลาย. เครื่องมือเพิ่มประสิทธิภาพการค้นหาได้ทำการเพิ่มประสิทธิภาพการตรวจสอบความถูกต้องของ 'คีย์เดียว - คีย์ต่างประเทศ' โดยใช้ MERGE JOIN และสร้างเฉพาะสำหรับฝ่ายขายตารางผู้ส่งสินค้าออกจาก LOOP JOIN สำหรับการรวมอื่นในการสืบค้นในเวลาเดียวกัน เนื่องจากฉันมีไม่กี่แถวในตารางหลักของเครื่องมือค้นหาข้อความใช้อัลกอริธึมการรวม Sort-merge และเปรียบเทียบแต่ละแถวในตารางภายในกับตารางหลักเพียงครั้งเดียว ดังนั้นนั่นคือคำตอบสำหรับคำถามของฉันหากมีกลไกเฉพาะใด ๆ ในการประมวลผลค่าเดียวในชุดในระหว่างการตรวจสอบความถูกต้องของคีย์เดียว นั่นไม่ใช่การตัดสินใจที่สมบูรณ์แบบ แต่นั่นคือวิธีที่ SQL Server ปรับเคสให้เหมาะสม
ผลกระทบต่อการสืบสวนพบว่าในกรณีของฉันคำสั่ง MERGE JOIN และ LOOP JOIN แทรกเท่ากับประมาณ 750 แถวที่แทรกพร้อมกันพร้อมกับความเหนือกว่าของ MERGE JOIN (ในทรัพยากรเวลา CPU) ดังนั้นการใช้ OPTION (LOOP JOIN) จึงเป็นทางออกที่เหมาะสมสำหรับกระบวนการทางธุรกิจของฉัน