ปัญหาการประมาณค่าเชิง Cardinality ของการเข้าร่วมวงใน


13

ฉันพยายามเข้าใจว่าทำไมการประมาณแถวจึงผิดอย่างยิ่งนี่คือกรณีของฉัน:

เข้าร่วมง่าย - โดยใช้ SQL Server 2016 sp2 (ปัญหาเดียวกันใน sp1), dbcompatiblity = 130

select Amount_TransactionCurrency_id, CurrencyShareds.id 
from CurrencyShareds 
    INNER JOIN annexes ON Amount_TransactionCurrency_id = CurrencyShareds.Id 
option (QUERYTRACEON 3604, QUERYTRACEON 2363);

SQL ประมาณ 1 แถวโดยที่ 107131 และเลือกวนซ้ำซ้อนกัน ( ลิงก์ไปยังแผน ) หลังจากอัปเดตสถิติใน CurrencyShared แล้วการประมาณการก็ใช้ได้และการเลือกผสานเข้าร่วม ( ลิงก์ไปยังแผนใหม่ ) ทันทีที่มีการเพิ่มเพียงหนึ่งระเบียนใน CurrencyShareds สถิติก็จะกลายเป็น "เก่า" และ sql กลับไปสู่การประเมินที่ผิด

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

ทำไมการเพิ่มหนึ่งแถวใน 100 ระเบียนตารางทำให้เกิดความเสียหายดังกล่าว เมื่อดูผลลัพธ์ของร่องรอยการประมาณค่าการเต้นของ***WARNING: badly-formed histogram ***หัวใจฉันเห็นคำเตือนนี้แต่ฉันไม่พบอะไรเพิ่มเติมในหัวข้อนี้

นี่คือผลลัพธ์เอาต์พุตเต็มรูปแบบจากการประมาณเชิง cardinality:

Begin selectivity computation
Input tree:

LogOp_Join

CStCollBaseTable(ID=1, CARD=107131 TBL: annexes)

CStCollBaseTable(ID=2, CARD=100 TBL: CurrencyShareds)

ScaOp_Comp x_cmpEq

ScaOp_Identifier QCOL: [test.MasterData].[dbo].[CurrencyShareds].Id

ScaOp_Identifier QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id

Plan for computation:

CSelCalcExpressionComparedToExpression( QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id x_cmpEq QCOL: [test.MasterData].[dbo].[CurrencyShareds].Id )

Loaded histogram for column QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id from stats with id 7

Loaded histogram for column QCOL: [test.MasterData].[dbo].[CurrencyShareds].Id from stats with id 1 *** WARNING: badly-formed histogram ***

Selectivity: 4.59503e-018

Stats collection generated:

CStCollJoin(ID=3, CARD=1 x_jtInner)

CStCollBaseTable(ID=1, CARD=107131 TBL: annexes)

CStCollBaseTable(ID=2, CARD=100 TBL: CurrencyShareds)

End selectivity computation

Estimating distinct count in utility function

Input stats collection:

CStCollBaseTable(ID=1, CARD=107131 TBL: annexes)

Columns to distinct on:QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id

Plan for computation:

CDVCPlanLeaf

0 Multi-Column Stats, 1 Single-Column Stats, 0 Guesses

Covering multi-col stats id: 7

Using ambient cardinality 107131 to combine distinct counts:

5

Combined distinct count: 5

Result of computation: 5

Estimating distinct count in utility function

Input stats collection:

CStCollBaseTable(ID=2, CARD=100 TBL: CurrencyShareds)

Columns to distinct on:QCOL: [test.MasterData].[dbo].[CurrencyShareds].Id

Plan for computation:

CDVCPlanUniqueKey

Result of computation: 100

และเมื่อฉันอัปเดตสถิติใน CurrencyShareds ส่วนที่มีการเปลี่ยนแปลง "ฮิสโตแกรมที่ไม่ดี" และการคำนวณ cardinality ถูกต้อง

Plan for computation:

CSelCalcExpressionComparedToExpression( QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id x_cmpEq QCOL: [test.MasterData].[dbo].[CurrencyShareds].Id )

Loaded histogram for column QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id from stats with id 7

Loaded histogram for column QCOL: [test.MasterData].[dbo].[CurrencyShareds].Id from stats with id 1

Selectivity: 0.01

Stats collection generated:

CStCollJoin(ID=3, CARD=107131 x_jtInner)

CStCollBaseTable(ID=1, CARD=107131 TBL: annexes)

CStCollBaseTable(ID=2, CARD=100 TBL: CurrencyShareds)

End selectivity computation

และข้อมูลสถิติสำหรับ "[CurrencyShareds]. นี้จากสถิติที่มี id 1" พร้อมคำเตือนเกี่ยวกับฮิสโตแกรมซึ่งดูดีสำหรับฉัน ...

Name                                                                                                                             Updated              Rows                 Rows Sampled         Steps  Density       Average key length String Index Filter Expression                                                                                                                                                                                                                                                Unfiltered Rows      Persisted Sample Percent
-------------------------------------------------------------------------------------------------------------------------------- -------------------- -------------------- -------------------- ------ ------------- ------------------ ------------ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------- ------------------------
PK_CurrencyShareds_Id                                                                                                            May 23 2018 10:43PM  98                   98                   75     1             8                  NO           NULL                                                                                                                                                                                                                                                             98                   0

(1 row affected)

All density   Average Length Columns
------------- -------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
0,01020408    8              Id

(1 row affected)

RANGE_HI_KEY         RANGE_ROWS    EQ_ROWS       DISTINCT_RANGE_ROWS  AVG_RANGE_ROWS
-------------------- ------------- ------------- -------------------- --------------
119762190797406464   0             1             0                    1
119762190797406466   1             1             1                    1
119762190797406468   1             1             1                    1
119762190797406470   1             1             1                    1
119762190797406472   1             1             1                    1
119762190797406474   1             1             1                    1
119762190797406476   1             1             1                    1
119762190797406478   1             1             1                    1
119762190797406480   1             1             1                    1
119762190797406482   1             1             1                    1
119762190797406484   1             1             1                    1
119762190797406486   1             1             1                    1
119762190797406488   1             1             1                    1
119762190797406490   1             1             1                    1
119762190797406492   1             1             1                    1
119762190797406494   1             1             1                    1
119762190797406496   1             1             1                    1
119762190797406498   1             1             1                    1
119762190797406500   1             1             1                    1
119762190797406502   1             1             1                    1
119762190797406504   1             1             1                    1
119762190797406506   1             1             1                    1
119762190797406507   0             1             0                    1
478531702587687680   0             1             0                    1
478531702591881728   0             1             0                    1
478531702591881729   0             1             0                    1
478531702591881984   0             1             0                    1
478531702591881985   0             1             0                    1
478531702596076032   0             1             0                    1
478531702596076033   0             1             0                    1
478531702596076288   0             1             0                    1
478531702600270336   0             1             0                    1
478531702600270592   0             1             0                    1
478532235583062528   0             1             0                    1
478532235583062784   0             1             0                    1
478532235587256832   0             1             0                    1
530792464911467264   0             1             0                    1
530792464924049920   0             1             0                    1
530792464924050176   0             1             0                    1
530792464928244224   0             1             0                    1
530792464928244480   0             1             0                    1
530792464932438528   0             1             0                    1
530792464932438784   0             1             0                    1
530792464936632832   0             1             0                    1
530792464936632833   0             1             0                    1
530792464936633088   0             1             0                    1
530792464940827136   0             1             0                    1
530792464940827392   0             1             0                    1
530792464949216000   2             1             2                    1
530792464953410048   0             1             0                    1
530792464953410304   0             1             0                    1
530792464957604352   0             1             0                    1
530792464957604353   0             1             0                    1
530792464957604608   0             1             0                    1
530792464961798656   0             1             0                    1
530792464961798912   0             1             0                    1
530792464965992960   0             1             0                    1
530792464965993216   0             1             0                    1
530792464965993217   0             1             0                    1
530792464970187264   0             1             0                    1
530792464970187265   0             1             0                    1
530792464970187520   0             1             0                    1
530792464974381568   0             1             0                    1
530792464974381824   0             1             0                    1
530792464974381825   0             1             0                    1
530792464978575872   0             1             0                    1
530792464978575873   0             1             0                    1
530792464978576128   0             1             0                    1
867420708903354880   0             1             0                    1
867420708903355136   0             1             0                    1
867420708903355137   0             1             0                    1
960876568220042240   0             1             0                    1
976385263448130048   0             1             0                    1
977302121709864192   0             1             0                    1
977955748426318592   0             1             0                    1

และข้อมูลสำหรับดัชนีที่สอง:

Name                                                                                                                             Updated              Rows                 Rows Sampled         Steps  Density       Average key length String Index Filter Expression                                                                                                                                                                                                                                                Unfiltered Rows      Persisted Sample Percent
-------------------------------------------------------------------------------------------------------------------------------- -------------------- -------------------- -------------------- ------ ------------- ------------------ ------------ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------- ------------------------
IX_FK_Amount_TransactionCurrency                                                                                                 May 21 2018  3:29PM  107204               107204               5      0             16                 NO           NULL                                                                                                                                                                                                                                                             107204               0

(1 row affected)

All density   Average Length Columns
------------- -------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
0,2           8              Amount_TransactionCurrency_id
9,32801E-06   16             Amount_TransactionCurrency_id, Id

(2 rows affected)

RANGE_HI_KEY         RANGE_ROWS    EQ_ROWS       DISTINCT_RANGE_ROWS  AVG_RANGE_ROWS
-------------------- ------------- ------------- -------------------- --------------
119762190797406475   0             160           0                    1
119762190797406478   0             867           0                    1
119762190797406481   0             106           0                    1
119762190797406494   0             105742        0                    1
119762190797406496   0             329           0                    1

คำตอบ:


10

ขึ้นอยู่กับ histograms ของคุณก็สามารถที่จะreproปัญหาในปี 2017 CU6 ฉันจะไม่บอกว่าคุณกำลังทำอะไรผิด แต่มีบางอย่างผิดปกติกับการประมาณค่าเชิง Cardinality นี่คือสิ่งที่ฉันได้รับก่อนที่จะแทรกแถว:

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

การประเมินความสำคัญเชิงหัวใจสุดท้ายลดลงเล็กน้อยหลังจากแทรกแถว:

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

คุณมีข้อผิดพลาดที่เรียบง่ายที่นี่ดังนั้นคำแนะนำของฉันคือยื่นคำติชมผลิตภัณฑ์หรือเปิดตั๋วการสนับสนุนกับ Microsoft ฉันสามารถค้นหาวิธีแก้ไขปัญหาเล็กน้อยที่ทำงานกับข้อมูลตัวอย่างของคุณและวิธีการหนึ่งอาจเป็นที่ยอมรับสำหรับคุณ

  1. CurrencyShareds.Idวางดัชนีที่ไม่ซ้ำกัน ฉันไม่สามารถรับการทำงานโดยไม่ใช้ดัชนีที่ไม่ซ้ำกัน ตารางมีขนาดเล็กดังนั้นคุณอาจได้รับโดยไม่มีดัชนี แน่นอนคุณอาจมีเหตุผลที่ดีมากในการรักษามันไว้
  2. แสดงผลลัพธ์ของการเข้าร่วมเป็นตารางชั่วคราว จากคำถามของคุณเป็นสิ่งสำคัญที่จะต้องได้รับการประเมินอย่างสมเหตุสมผลในขั้นตอนนี้เพื่อให้การสืบค้นที่มีขนาดใหญ่ขึ้นนั้นมีประสิทธิภาพดี ตารางอุณหภูมิเป็นวิธีหนึ่งในการทำให้เกิดขึ้น
  3. ใช้ CE ดั้งเดิม ฉันไม่สามารถรับปัญหาที่จะทำซ้ำได้ แน่นอนว่าสิ่งนี้อาจส่งผลเสียต่อการสืบค้นที่เหลือของคุณ
  4. หลอกลวงเครื่องมือเพิ่มประสิทธิภาพการสืบค้นด้วยรหัสโง่ ตัวอย่างเช่นในการทดสอบของฉันการเขียนต่อไปนี้ใช้งานได้ดี:

.

select Amount_TransactionCurrency_id, CurrencyShareds.id
from CurrencyShareds 
INNER JOIN annexes
ON Amount_TransactionCurrency_id % 9223372036854775809 = CurrencyShareds.Id % 9223372036854775809

ฉันสงสัยว่าสิ่งนี้ใช้ได้เพราะ CE ดูเหมือนจะใช้ความหนาแน่นแทนฮิสโตแกรม การเขียนซ้ำที่คล้ายกันอื่น ๆ อาจมีผลเหมือนกัน ไม่มีการรับประกันว่าแบบสอบถามชนิดใดจะยังคงทำงานได้ดีในอนาคต นั่นเป็นเหตุผลที่คุณควรติดต่อ Microsoft เพื่อปรับปรุงราคาที่วันหนึ่งการแก้ไขปัญหาของคุณจะทำให้เป็นผลิตภัณฑ์ที่วางจำหน่าย


8

โอเคฉันหวังว่าฉันเข้าใจแล้ว - ดังนั้นกรณีของเรา

ได้รับ

  1. ตารางอ้างอิง (CurrencyShareds) ที่มี ~ 100 แถว แต่รหัสมีขนาดใหญ่และต่ำสุดค่าสูงสุดแตกต่างกันมาก - ต่ำสุด: 119,762,190,797,406,464 vs สูงสุด: 977,955,748,426,318,592
  2. ตาราง (ภาคผนวก) ที่มี FK เป็น CurrencyShared อย่างง่าย แต่มีการใช้สกุลเงินเพียงเล็กน้อยคุณสามารถดูฮิสโตแกรมนั้นสำหรับ IX_FK_Amount_TransactionCurrency แสดงรายการ 5 รหัส - และสิ่งที่มีความสำคัญเฉพาะรหัส "ต่ำ" ดังที่ไม่ได้ใช้

เมื่อสถิติทั้งหมดเป็นปัจจุบันแล้ว

CSelCalcExpressionComparedToExpression( QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id x_cmpEq QCOL: [test.MasterData].[dbo].[CurrencyShareds].Id )

Loaded histogram for column QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id from stats with id 7

Loaded histogram for column QCOL: [test.MasterData].[dbo].[CurrencyShareds].Id from stats with id 1

Selectivity: 0.01

จากนั้นการเลือกหัวที่คำนวณได้สำหรับการเข้าร่วมนั้นไม่เป็นเช่น 100 * 107,131 * 0.01 = 107,131

เมื่อสถิติของกระแสข้อมูลไม่เป็นปัจจุบัน

CSelCalcExpressionComparedToExpression( QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id x_cmpEq QCOL: [test.MasterData].[dbo].[CurrencyShareds].Id )

Loaded histogram for column QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id from stats with id 7

Loaded histogram for column QCOL: [test.MasterData].[dbo].[CurrencyShareds].Id from stats with id 1 *** WARNING: badly-formed histogram ***

Selectivity: 4.59503e-018

หัวกะทิลดลงอย่างมากและด้วยเหตุนี้จำนวนแถวโดยประมาณของการเข้าร่วมคือ 1

เมื่อฮิสโตแกรมเปลี่ยนไป

หลังจากที่ฉันเพิ่มแถวเดียวลงในภาคผนวกที่ refends ค่า CurrencyShared ที่มี id สูงจากนั้นผลลัพธ์จะแสดงฮิสโตแกรมสำหรับ IX_FK_Amount_TransactionCurrency เปลี่ยนเป็น

RANGE_HI_KEY         RANGE_ROWS    EQ_ROWS       DISTINCT_RANGE_ROWS  AVG_RANGE_ROWS
-------------------- ------------- ------------- -------------------- --------------
119762190797406475   0             173           0                    1
119762190797406478   0             868           0                    1
119762190797406481   0             107           0                    1
119762190797406494   0             105745        0                    1
119762190797406496   0             330           0                    1
119762190797406618   0             1             0                    1
119762190797406628   0             1             0                    1
977955748426318623   0             1             0                    1

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

ทำไมถึงเป็นอย่างนั้น?

ฉันสงสัยว่านี่คือวิธีการคำนวณฮิสโตแกรมหยาบใน sql2014 + และฉันคาดเดาการโพสต์ที่ยอดเยี่ยมนี้https://www.sqlshack.com/join-estimation-internals/

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

เพียงเพื่อทำให้ทุกอย่างชัดเจน - ทำไมเราถึงมีรหัสแปลก ๆ เช่นนี้ในกระแสน้ำเชี่ยว

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

ปัญหาที่เกิดขึ้นในสภาพแวดล้อมการทดสอบของเราซึ่งการทดสอบอัตโนมัติบางอย่างเริ่มเพิ่มสกุลเงินการทดสอบทำให้บางคำสั่งทำงานได้นานขึ้นหรือหมดเวลา ...

วิธีแก้ไขปัญหา

เราจะอัปเดตสถิติสำหรับตารางอ้างอิงเหล่านั้น (เราอาจมีปัญหาที่คล้ายกันกับตารางข้อมูลอ้างอิงอื่น ๆ ที่คล้ายกัน) บ่อยขึ้น - ตารางเหล่านั้นมีขนาดเล็กดังนั้นการอัปเดตสถิติไม่ได้เป็นปัญหา

บทเรียนที่ได้รับ

  • สถิติล่าสุดมีความสำคัญ !!!
  • คอลัมน์ identity เก่าแบบธรรมดาจะไม่ทำให้เกิดปัญหาเหล่านี้ :)

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