เหตุใดแบบสอบถามย่อยจึงใช้การขนานและการเข้าร่วมไม่ได้


16

เหตุใดเซิร์ฟเวอร์ SQL จึงใช้ความขนานเมื่อเรียกใช้แบบสอบถามนี้ซึ่งใช้แบบสอบถามย่อย แต่ไม่ใช้เมื่อเข้าร่วม เวอร์ชันการเข้าร่วมจะทำงานเป็นอนุกรมและใช้เวลาดำเนินการนานกว่าประมาณ 30 เท่า

เข้าร่วมเวอร์ชัน: ~ 30 วินาที

ป้อนคำอธิบายรูปภาพที่นี่

เวอร์ชันย่อยของแบบสอบถาม: <1 วินาที

ป้อนคำอธิบายรูปภาพที่นี่

แก้ไข: แผนแบบสอบถามเวอร์ชัน Xml:

เข้าร่วมเวอร์ชัน

รุ่น SUBQUERY

คำตอบ:


12

ตามที่ระบุไว้แล้วในความคิดเห็นดูเหมือนว่าคุณจำเป็นต้องปรับปรุงสถิติของคุณ

จำนวนแถวโดยประมาณที่มาจากการเข้าร่วมระหว่างlocationและtestrunsแตกต่างกันอย่างมากระหว่างสองแผน

เข้าร่วมประมาณการแผน: 1

แผน 1

ประมาณการแผนแบบสอบถามย่อย: 8,748

ป้อนคำอธิบายรูปภาพที่นี่

จำนวนแถวที่แท้จริงจากการเข้าร่วมคือ 14,276

แน่นอนว่าไม่มีเหตุผลใด ๆ ที่เข้าใจง่ายว่ารุ่นเข้าร่วมควรประมาณว่า 3 แถวควรมาจากlocationและสร้างแถวเข้าร่วมเดียวในขณะที่แบบสอบถามย่อยประมาณว่าแถวเดียวจะสร้าง 8,748 จากการเข้าร่วมเดียวกัน แต่อย่างไรก็ตามฉันก็สามารถ เพื่อทำซ้ำสิ่งนี้

สิ่งนี้ดูเหมือนว่าจะเกิดขึ้นหากไม่มีการข้ามระหว่างฮิสโตแกรมเมื่อสร้างสถิติ เวอร์ชันเข้าร่วมถือว่าเป็นแถวเดียว และการค้นหาความเท่าเทียมกันครั้งเดียวของเคียวรีย่อยจะถือว่าแถวที่ประมาณไว้เหมือนกันกับการค้นหาความเท่าเทียมกันกับตัวแปรที่ไม่รู้จัก

cardinality ของ testruns 26244คือ สมมติว่ามีประชากรพร้อมรหัสสถานที่แตกต่างกันสามรหัสดังนั้นแบบสอบถามต่อไปนี้จะประมาณว่า8,748จะส่งคืนแถว ( 26244/3)

declare @i int

SELECT *
FROM   testruns AS tr
WHERE  tr.location_id = @i

เนื่องจากตารางlocationsมีเพียง 3 แถวเท่านั้นจึงเป็นเรื่องง่าย (ถ้าเราไม่มีคีย์ต่างประเทศ) เพื่อสร้างสถานการณ์ที่มีการสร้างสถิติจากนั้นข้อมูลจะถูกเปลี่ยนแปลงในลักษณะที่ส่งผลกระทบต่อจำนวนแถวจริงที่ส่งคืน แต่กลับไม่เพียงพอ เดินทางไปที่การอัปเดตอัตโนมัติของสถิติและเกณฑ์การคอมไพล์ซ้ำ

ในขณะที่ SQL Server รับจำนวนแถวที่มาจากการเข้าร่วมนั้นดังนั้นการประมาณการแถวอื่น ๆ ทั้งหมดในแผนการเข้าร่วมจึงประเมินค่าต่ำเกินไป tempdbเช่นเดียวกับความหมายที่คุณได้รับแผนอนุกรมแบบสอบถามยังได้รับทุนหน่วยความจำไม่เพียงพอและทุกประเภทและกัญชาเข้าร่วมการรั่วไหลไป

สถานการณ์หนึ่งที่เป็นไปได้ที่จะสร้างแถวจริงเทียบกับแถวโดยประมาณที่แสดงในแผนของคุณอยู่ด้านล่าง

CREATE TABLE location
  (
     id       INT CONSTRAINT locationpk PRIMARY KEY,
     location VARCHAR(MAX) /*From the separate filter think you are using max?*/
  )

/*Temporary ids these will be updated later*/
INSERT INTO location
VALUES      (101, 'Coventry'),
            (102, 'Nottingham'),
            (103, 'Derby')

CREATE TABLE testruns
  (
     location_id INT
  )

CREATE CLUSTERED INDEX IX ON testruns(location_id)

/*Add in 26244 rows of data split over three ids*/
INSERT INTO testruns
SELECT TOP (5984) 1
FROM   master..spt_values v1, master..spt_values v2
UNION ALL
SELECT TOP (5984) 2
FROM   master..spt_values v1, master..spt_values v2
UNION ALL
SELECT TOP (14276) 3
FROM   master..spt_values v1, master..spt_values v2

/*Create statistics. The location_id histograms don't intersect at all*/
UPDATE STATISTICS location(locationpk) WITH FULLSCAN;    
UPDATE STATISTICS testruns(IX) WITH FULLSCAN;

/* UPDATE location.id. Three row update is below recompile threshold*/
UPDATE location
SET    id = id - 100

จากนั้นการเรียกใช้คิวรีต่อไปนี้ให้ค่าความคลาดเคลื่อนที่เกิดขึ้นจริงเทียบกับค่าประมาณเดียวกัน

SELECT *
FROM   testruns AS tr
WHERE  tr.location_id = (SELECT id
                         FROM   location
                         WHERE  location = 'Derby')

SELECT *
FROM   testruns AS tr
       JOIN location loc
         ON tr.location_id = loc.id
WHERE  loc.location = ( 'Derby' ) 

หากมีการเพิ่มข้อ จำกัด ที่ไม่ซ้ำกันในสถานที่จะเห็นได้ชัดว่า "=" จะส่งคืนแถวเดียว จากนั้นในตัวอย่างของคุณแผนการสืบค้นจะเหมือนกัน (สแกน -> ค้นหา): แก้ไขตารางตำแหน่งเพิ่มข้อ จำกัด U_Location_Location ที่ไม่ซ้ำกันแบบไม่คลัสเตอร์ (สถานที่);
crokusek

@crokusek ใช่ ตระหนักถึงสิ่งที่คุณหมายถึงหลังจากนั้นและลบความคิดเห็นของฉัน! สิ่งนี้จะเพิ่มจำนวนแถวโดยประมาณเพื่อให้เวอร์ชันการรวมเป็นเหมือนแบบสอบถามย่อยหรือไม่ ไม่ได้ทดสอบบนพีซีในขณะนี้?
Martin Smith

@crokusek Yep ดูเหมือนว่าแถวโดยประมาณที่เหมือนกันจากการเข้าร่วมเป็นแบบสอบถามย่อยในกรณีซิงเกิลนั้น
Martin Smith

ใช่. แผนการค้นหาที่เหมือนกันทั้งสองประมาณการ 8748 ทั้งจริง 14,276 ล้านบาทฉันคิดว่าการคำนวณตำแหน่งก่อนจะแก้ไขความแตกต่างนั้น แต่ก็ไม่ได้
crokusek

1
@crokusek - ฉันจะเพิ่มข้อ จำกัด ที่ไม่ซ้ำกันให้กับสถานที่และสถานที่ที่คล้ายกันอื่น ๆ ภายในฐานข้อมูลของฉัน ฉันต้องยอมรับว่าไม่ได้รับรู้ว่ามีผลต่อการเพิ่มประสิทธิภาพการค้นหา ฉันคิดว่ามันเป็นเพียงการรับรองความถูกต้องของข้อมูล ขอบคุณสำหรับการป้อนข้อมูลของคุณสำหรับคำถามนี้
Chris L
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.