เหตุใดผู้ดำเนินการเชื่อมต่อจึงประมาณค่าแถวน้อยกว่าอินพุต


20

ในตัวอย่างแบบสอบถามแผนต่อไปนี้ดูเหมือนว่าชัดเจนว่าการประมาณแถวสำหรับConcatenationผู้ประกอบการควรเป็น~4.3 billion rowsหรือผลรวมของแถวประมาณการสำหรับสองอินพุต

อย่างไรก็ตามมีการประมาณค่าการ~238 million rowsผลิตซึ่งนำไปสู่การเพิ่มประสิทธิภาพย่อยSort/ Stream Aggregateกลยุทธ์ที่กระจายข้อมูลหลายร้อย GB ไปยัง tempdb การประมาณที่สอดคล้องกันอย่างมีเหตุผลในกรณีนี้จะทำให้เกิด a Hash Aggregateลบการรั่วไหลและเพิ่มประสิทธิภาพของแบบสอบถาม

นี่เป็นข้อบกพร่องใน SQL Server 2014 หรือไม่ มีสถานการณ์ที่ถูกต้องหรือไม่ที่การประมาณการต่ำกว่าอินพุทอาจมีเหตุผลหรือไม่? วิธีแก้ไขปัญหาใดบ้างที่อาจมีอยู่

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

นี่คือแผนแบบสอบถามเต็มรูปแบบ (ไม่ระบุชื่อ) ฉันไม่สามารถดูแลระบบเข้าถึงเซิร์ฟเวอร์นี้เพื่อให้เอาต์พุตจากQUERYTRACEON 2363หรือแฟล็กการติดตามที่คล้ายกัน แต่อาจสามารถรับเอาต์พุตเหล่านี้จากผู้ดูแลระบบหากพวกเขาจะเป็นประโยชน์

ฐานข้อมูลอยู่ในระดับความเข้ากันได้ 120 ดังนั้นจึงใช้เครื่องมือประมาณการ Cardinality ใหม่ของ SQL Server 2014

สถิติจะถูกอัพเดตด้วยตนเองทุกครั้งที่มีการโหลดข้อมูล เมื่อพิจารณาจากปริมาณข้อมูลเรากำลังใช้อัตราการสุ่มตัวอย่างเริ่มต้น เป็นไปได้ว่าอัตราการสุ่มตัวอย่างที่สูงขึ้น (หรือFULLSCAN) อาจมีผลกระทบ

คำตอบ:


21

หากต้องการอ้างอิง Campbell Fraser ในรายการเชื่อมต่อนี้ :

"ความไม่สอดคล้องของ cardinality" เหล่านี้สามารถเกิดขึ้นได้ในหลาย ๆ สถานการณ์รวมถึงเวลาที่ใช้ concat สิ่งเหล่านี้สามารถเกิดขึ้นได้เนื่องจากการประมาณค่าของทรีย่อยที่เฉพาะเจาะจงในแผนขั้นสุดท้ายอาจได้รับการทำให้สมบูรณ์ในโครงสร้างย่อยที่แตกต่างกัน เนื่องจากลักษณะทางสถิติของการประมาณเชิงหัวใจการประเมินบนต้นไม้ที่แตกต่างกัน แต่มีเหตุผลเทียบเท่าจึงไม่รับประกันว่าจะได้รับการประเมินแบบเดียวกัน ดังนั้นจึงไม่มีการรับประกันความมั่นคงที่คาดหวังไว้โดยรวม

ในการขยายตัวเพียงเล็กน้อย: วิธีที่ฉันชอบจะอธิบายก็คือการประมาณว่าcardinality เบื้องต้น (ดำเนินการก่อนการปรับให้เหมาะสมตามต้นทุนเริ่มต้น) จะสร้างการประมาณของ cardinality ที่ "สอดคล้องกัน" มากขึ้นเนื่องจากต้นไม้เริ่มต้นทั้งหมดถูกประมวลผล ค่าประมาณขึ้นอยู่กับค่าก่อนหน้าโดยตรง

ในระหว่างการปรับให้เหมาะสมตามต้นทุนส่วนของแผนผังแผน (หนึ่งตัวดำเนินการหรือมากกว่า) อาจถูกสำรวจและแทนที่ด้วยทางเลือกซึ่งแต่ละอย่างอาจต้องมีการประเมินความสำคัญเชิงหัวใจใหม่ ไม่มีวิธีทั่วไปที่จะบอกว่าการประเมินแบบใดจะดีกว่าแบบอื่นดังนั้นจึงเป็นไปได้ที่จะจบลงด้วยแผนสุดท้ายที่ปรากฏว่า "ไม่สอดคล้อง" นี่เป็นเพียงผลจากการประสาน "บิตของแผน" เข้าด้วยกันเพื่อจัดเรียงขั้นสุดท้าย

ทั้งหมดที่กล่าวมามีการเปลี่ยนแปลงรายละเอียดบางอย่างเกี่ยวกับ cardinality estimator (CE) ใหม่ที่นำมาใช้ใน SQL Server 2014 ซึ่งทำให้สิ่งนี้ค่อนข้างน้อยกว่ากรณีที่เกิดขึ้นกับ CE ดั้งเดิม

นอกเหนือจากการอัปเกรดเป็นอัปเดตสะสมล่าสุดและการตรวจสอบว่าเครื่องมือเพิ่มประสิทธิภาพด้วย 4199 เปิดใช้งานแล้วตัวเลือกหลักของคุณคือลองเปลี่ยนสถิติ / ดัชนี (สังเกตคำเตือนสำหรับดัชนีที่หายไป) และอัปเดตหรือแสดงคิวรีแตกต่างกัน เป้าหมายที่จะได้รับแผนการที่แสดงพฤติกรรมที่คุณต้องการ สิ่งนี้อาจถูกแช่แข็งพร้อมกับคู่มือแผนเป็นต้น

แผนแบบไม่ระบุชื่อทำให้ยากที่จะประเมินรายละเอียด แต่ฉันก็จะพิจารณาบิตแมปอย่างละเอียดเพื่อดูว่าเป็นของ 'ปรับให้เหมาะสม' (Opt_Bitmap) หรือความหลากหลายหลังการปรับให้เหมาะสม (บิตแมป) ฉันยังสงสัยตัวกรองด้วย

หากการนับแถวเป็นอะไรที่ถูกต้องแม้ว่านี่จะดูเหมือนว่าแบบสอบถามที่อาจได้รับประโยชน์จาก columnstore นอกเหนือจากสิทธิประโยชน์ปกติแล้วคุณอาจสามารถใช้ประโยชน์จากหน่วยความจำแบบไดนามิกสำหรับผู้ประกอบการโหมดแบตช์ ( อาจจำเป็นต้องตั้งค่าสถานะการติดตาม 9389 )


7

สร้างเตียงทดสอบที่ยอมรับค่อนข้างง่ายใน SQL Server 2012 (11.0.6020) UNION ALLช่วยให้ฉันเพื่อสร้างแผนสองคำสั่งกัญชาจับคู่ถูกตัดแบ่งผ่าน เตียงทดสอบของฉันไม่แสดงการประมาณที่ไม่ถูกต้องที่คุณเห็น บางทีนี่อาจเป็นปัญหาของ SQL Server 2014 CE

ฉันได้รับการประมาณ 133.785 แถวสำหรับแบบสอบถามที่จริงแล้วส่งคืน 280 แถวอย่างไรก็ตามจะต้องมีการคาดหวังเนื่องจากเราจะเห็นข้อมูลเพิ่มเติมเกี่ยวกับ:

IF OBJECT_ID('dbo.Union1') IS NOT NULL
DROP TABLE dbo.Union1;
CREATE TABLE dbo.Union1
(
    Union1_ID INT NOT NULL
        CONSTRAINT PK_Union1
        PRIMARY KEY CLUSTERED
        IDENTITY(1,1)
    , Union1_Text VARCHAR(255) NOT NULL
    , Union1_ObjectID INT NOT NULL
);

IF OBJECT_ID('dbo.Union2') IS NOT NULL
DROP TABLE dbo.Union2;
CREATE TABLE dbo.Union2
(
    Union2_ID INT NOT NULL
        CONSTRAINT PK_Union2
        PRIMARY KEY CLUSTERED
        IDENTITY(2,2)
    , Union2_Text VARCHAR(255) NOT NULL
    , Union2_ObjectID INT NOT NULL
);

INSERT INTO dbo.Union1 (Union1_Text, Union1_ObjectID)
SELECT o.name, o.object_id
FROM sys.objects o;

INSERT INTO dbo.Union2 (Union2_Text, Union2_ObjectID)
SELECT o.name, o.object_id
FROM sys.objects o;
GO

SELECT *
FROM dbo.Union1 u1
    INNER HASH JOIN sys.objects o ON u1.Union1_ObjectID = o.object_id
UNION ALL
SELECT *
FROM dbo.Union2 u2
    INNER HASH JOIN sys.objects o ON u2.Union2_ObjectID = o.object_id;

ฉันคิดว่าเหตุผลอยู่ที่การขาดสถิติสำหรับการรวมสองรายการที่เกิดขึ้นกับ UNION SQL Server จำเป็นต้องคาดเดาอย่างมีเหตุผลในกรณีส่วนใหญ่เกี่ยวกับการเลือกคอลัมน์เมื่อต้องเผชิญกับการขาดสถิติ

โจกระสอบมีการอ่านที่น่าสนใจเกี่ยวกับที่นี่

สำหรับ a UNION ALLปลอดภัยที่จะบอกว่าเราจะเห็นจำนวนแถวทั้งหมดที่คืนมาจากแต่ละส่วนประกอบของสหภาพอย่างแน่นอนอย่างไรก็ตามเนื่องจาก SQL Server ใช้การประมาณแถวสำหรับองค์ประกอบทั้งสองของUNION ALLเราจึงเห็นว่ามันเพิ่มจำนวนแถวโดยประมาณทั้งหมดจากทั้งสอง แบบสอบถามที่จะเกิดขึ้นกับการประมาณการสำหรับผู้ประกอบการเรียงต่อกัน

ในตัวอย่างของฉันข้างต้นจำนวนแถวโดยประมาณสำหรับแต่ละส่วนของUNION ALL66.8927 ซึ่งเมื่อรวมเท่ากับ 133.785 ซึ่งเราเห็นจำนวนแถวโดยประมาณสำหรับผู้ดำเนินการเชื่อมต่อ

แผนการดำเนินการจริงสำหรับคิวรีแบบร่วมด้านบนมีลักษณะดังนี้:

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

คุณสามารถดูจำนวนแถว "โดยประมาณ" เทียบกับ "จริง" ในกรณีของฉันการเพิ่มจำนวนแถว "โดยประมาณ" ที่ส่งคืนโดยผู้ดำเนินการจับคู่แฮชเท่ากับจำนวนเงินที่แสดงโดยผู้ดำเนินการเชื่อมต่อ

ฉันจะพยายามรับผลลัพธ์จากการติดตาม 2363 ฯลฯ ตามที่แนะนำในโพสต์ของ Paul White ที่คุณแสดงในคำถามของคุณ อีกวิธีหนึ่งคุณอาจลองใช้OPTION (QUERYTRACEON 9481)ในแบบสอบถามเพื่อเปลี่ยนกลับเป็น CE 70 รุ่นเพื่อดูว่า "แก้ไข" ปัญหา


1
ขอบคุณ ฉันได้เห็นอย่างแน่นอนว่า "เหตุผลอยู่ที่การขาดสถิติสำหรับการรวมสองรายการที่เป็นผลของ UNIONed" มีผลกระทบอย่างมากต่อการรวมหรือการรวมที่ตามมา (ซึ่งเกิดขึ้นหลังจากสหภาพ) SQL 2014 จัดการได้ดีกว่า SQL 2012 จริง ๆ ในประสบการณ์ของฉัน ต่อไปนี้เป็นสคริปต์ทดสอบอย่างง่ายที่ฉันเคยใช้ในอดีต: gist.github.com/anonymous/1497112d8b25ab8fb782a04569959c68 อย่างไรก็ตามฉันไม่คิดว่าผู้ดำเนินการเชื่อมต่อจะต้องมีข้อมูลแบบเดียวกันเกี่ยวกับการกระจายของค่าที่เข้าร่วม อาจต้องการ
Geoff Patterson

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