Cardinality Estimation สำหรับ> = และ> สำหรับค่าสถิติขั้นตอนภายใน


9

ฉันพยายามที่จะเข้าใจว่า SQL Server พยายามประเมิน 'มากกว่า' และ 'มากกว่าเท่ากับ' โดยที่ clauses ใน SQL Server 2014

ฉันคิดว่าฉันเข้าใจการประเมินความสำคัญเชิงหัวใจเมื่อมันกระทบกับขั้นตอนเช่นถ้าฉันทำ

    select * from charge where charge_dt >= '1999-10-13 10:47:38.550'

การประเมินความสำคัญเชิงหัวใจคือ 6672 ซึ่งสามารถคำนวณได้ง่ายเป็น 32 (EQ_ROWS) + 6624 (RANGE_ROWS) + 16 (EQ_ROWS) = 6672 (ฮิสโตแกรมในภาพด้านล่าง)

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

แต่เมื่อฉันทำ

    select * from charge where charge_dt >= '1999-10-13 10:48:38.550' 

(เพิ่มเวลาเป็น 10:48 ดังนั้นจึงไม่ใช่ขั้นตอน)

ค่าประมาณคือ 4844.13

คำนวณอย่างไร?

คำตอบ:


9

ความยากลำบากเพียงอย่างเดียวคือการตัดสินใจว่าจะจัดการกับขั้นตอนฮิสโตแกรมที่ครอบคลุมบางส่วนด้วยช่วงเวลาของเพรดิเคตแบบสอบถาม ขั้นตอนฮิสโตแกรมทั้งหมดที่ครอบคลุมโดยช่วงเพรดิเคตนั้นเล็กน้อยตามที่ระบุไว้ในคำถาม

เครื่องมือประเมินความผิดปกติแบบดั้งเดิม

F = ส่วน (ระหว่าง 0 ถึง 1) ของช่วงขั้นตอนที่ครอบคลุมโดยเพรดิเคตแบบสอบถาม

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

Cardinality = EQ_ROWS + (AVG_RANGE_ROWS * F * DISTINCT_RANGE_ROWS)

สูตรเดียวกันนี้ใช้สำหรับ>และ>=ใน CE ดั้งเดิม

เครื่องมือประมาณการความใหม่

ปรับเปลี่ยนใหม่ CE ขั้นตอนวิธีการก่อนหน้าเล็กน้อยเพื่อแยกความแตกต่างระหว่างและ>>=

การ>ครั้งแรกสูตรคือ:

Cardinality = EQ_ROWS + (AVG_RANGE_ROWS * (F * (DISTINCT_RANGE_ROWS - 1))

เพราะ>=มันคือ:

Cardinality = EQ_ROWS + (AVG_RANGE_ROWS * ((F * (DISTINCT_RANGE_ROWS - 1)) + 1)

+ 1สะท้อนให้เห็นว่าเมื่อเปรียบเทียบเกี่ยวข้องกับความเสมอภาคการแข่งขันจะสันนิษฐาน (สมมติฐานรวม)

ในตัวอย่างคำถามFสามารถคำนวณได้ดังนี้

DECLARE 
    @Q datetime = '1999-10-13T10:48:38.550',
    @K1 datetime = '1999-10-13T10:47:38.550',
    @K2 datetime = '1999-10-13T10:51:19.317';

DECLARE
    @QR float = DATEDIFF(MILLISECOND, @Q, @K2), -- predicate range
    @SR float = DATEDIFF(MILLISECOND, @K1, @K2) -- whole step range

SELECT
    F = @QR / @SR;

ผลที่ได้คือ0.728219019233034 การเสียบเข้ากับสูตรสำหรับ>=ค่าที่ทราบอื่น ๆ :

Cardinality = EQ_ROWS + (AVG_RANGE_ROWS * ((F * (DISTINCT_RANGE_ROWS - 1)) + 1)
            = 16 + (16.1956 * ((0.728219019233034 * (409 - 1)) + 1))
            = 16 + (16.1956 * ((0.728219019233034 * 408) + 1))
            = 16 + (16.1956 * (297.113359847077872 + 1))
            = 16 + (16.1956 * 298.113359847077872)
            = 16 + 4828.1247307393343837632
            = 4844.1247307393343837632
            = 4844.12473073933 (เพื่อความแม่นยำลอย)

ผลลัพธ์นี้สอดคล้องกับประมาณการของ 4844.13 ที่แสดงในคำถาม

ข้อความค้นหาเดียวกันโดยใช้ CE ดั้งเดิม (เช่นการใช้แฟล็กการติดตาม 9481) ควรสร้างการประมาณ:

Cardinality = EQ_ROWS + (AVG_RANGE_ROWS * F * DISTINCT_RANGE_ROWS)
            = 16 + (16.1956 * 0.728219019233034 * 409)
            = 16 + 4823.72307468722
            = 4839.72307468722

โปรดทราบว่าการประมาณการจะเหมือนกันสำหรับ>และ>=ใช้ CE ดั้งเดิม


4

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

ตัวเลข

ใช้ขั้นตอนที่ 193 ต่อไปนี้เป็นหมายเลขที่เกี่ยวข้อง:

RANGE_ROWS = 6624

EQ_ROWS = 16

AVG_RANGE_ROWS = 16.1956

RANGE_HI_KEY จากขั้นตอนก่อนหน้า = 1999-10-13 10: 47: 38.550

RANGE_HI_KEY จากขั้นตอนปัจจุบัน = 1999-10-13 10: 51: 19.317

ค่าจาก WHERE clause = 1999-10-13 10: 48: 38.550

สูตร

1) ค้นหา ms ระหว่างสองปุ่ม hi range

SELECT DATEDIFF (ms, '1999-10-13 10:47:38.550', '1999-10-13 10:51:19.317')

ผลลัพธ์คือ 220767 ms

2) ปรับจำนวนแถว

เราจำเป็นต้องค้นหาแถวต่อมิลลิวินาที แต่ก่อนที่เราจะทำเราต้องลบ AVG_RANGE_ROWS ออกจาก RANGE_ROWS:

6624 - 16.1956 = 6607.8044 แถว

3) คำนวณแถวต่อ ms ด้วยจำนวนแถวที่ปรับ:

6607.8044 แถว / 220767 ms = .0299311 แถวต่อ ms

4) คำนวณ ms ระหว่างค่าจากส่วนคำสั่ง WHERE และขั้นตอนปัจจุบัน RANGE_HI_KEY

SELECT DATEDIFF (ms, '1999-10-13 10:48:38.550', '1999-10-13 10:51:19.317')

สิ่งนี้ทำให้เรามีจำนวน 160767 มิลลิวินาที

5) คำนวณแถวในขั้นตอนนี้โดยยึดตามแถวต่อวินาที:

.0299311 แถว / ms * 160767 ms = 4811.9332 แถว

6) จำได้ไหมว่าเราจะลบ AVG_RANGE_ROWS ก่อนหน้านี้ได้อย่างไร ได้เวลาเพิ่มกลับ ตอนนี้เราทำการคำนวณตัวเลขที่เกี่ยวข้องกับแถวต่อวินาทีเสร็จแล้วเราสามารถเพิ่ม EQ_ROWS ได้อย่างปลอดภัย:

4811.9332 + 16.1956 + 16 = 4844.1288

ถูกปัดเศษนั่นคือค่าประมาณ 4844.13 ของเรา

ทดสอบสูตร

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

ด้วยการใช้ฐานข้อมูล WideWorldImportersฉันได้ทำการทดสอบที่เพิ่มขึ้นและพบว่าการประมาณแถวลดลงจะเป็นแบบเชิงเส้นจนกระทั่งสิ้นสุดขั้นตอนโดยที่ 1x AVG_RANGE_ROWS คิดเป็นสัดส่วน

นี่คือแบบสอบถามตัวอย่างของฉัน:

SELECT PickingCompletedWhen
FROM Sales.Orders
WHERE PickingCompletedWhen >= '2016-05-24 11:00:01.000000'

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

DBCC SHOW_STATISTICS([sales.orders], '_WA_Sys_0000000E_44CA3770')

ฮิสโตแกรมสำหรับ _WA_Sys_0000000E_44CA3770 (3 ขั้นตอนสุดท้าย)

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

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

สังเกตการลดลงอย่างต่อเนื่องในแถวจนกว่าเราจะกด RANGE_HI_KEY จากนั้นบูมที่ AVG_RANGE_ROWS อันสุดท้ายจะถูกลบออกทันที มันง่ายที่จะมองเห็นในกราฟด้วย

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

ในการสรุปการรักษา AVG_RANGE_ROWS ทำให้การคำนวณแถวมีความซับซ้อนมากขึ้น แต่คุณสามารถกระทบยอดสิ่งที่ CE กำลังทำอยู่เสมอ

Backoff แบบเอ็กซ์โปเนนเชียล

เอ็กซ์โพเนนเชียลแบ็คออฟเป็นวิธีการใหม่ (ณ วันที่ SQL Server 2014) Cardinality Estimator ใช้เพื่อให้ได้ค่าประมาณที่ดีขึ้นเมื่อใช้สถิติคอลัมน์เดี่ยวหลายคอลัมน์ เนื่องจากคำถามนี้เกี่ยวกับสถิติคอลัมน์เดียวหนึ่งคอลัมน์จึงไม่เกี่ยวข้องกับสูตร EB

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.