Masalah estimasi kardinalitas pada inner join

13

Saya berusaha memahami mengapa estimasi baris sangat keliru, inilah kasus saya:

Bergabung sederhana - menggunakan SQL Server 2016 sp2 (masalah yang sama pada 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 memperkirakan 1 baris, sedangkan 107131 dan memilih untuk melakukan loop bersarang ( tautan ke rencana ). Setelah statistik diperbarui pada CurrencyShareds maka estimasi baik-baik saja dan gabungan gabung dipilih ( tautan ke paket baru ). Segera setelah satu catatan ditambahkan ke CurrencyShareds, maka statistik menjadi "basi" dan sql kembali ke estimasi yang salah.

Saya tidak akan terlalu khawatir tentang permintaan sederhana ini, tetapi ini hanya bagian dari yang lebih besar, dan ini adalah awal dari domino ...

Mengapa menambahkan satu baris ke 100 tabel catatan menyebabkan kerusakan seperti itu? Ketika melihat ke dalam output dari jejak estimasi kardinalitas, saya melihat peringatan ini ***WARNING: badly-formed histogram ***tetapi saya tidak dapat menemukan lebih banyak tentang topik ini.

Ini adalah output hasil lengkap dari estimasi kardinalitas:

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

Dan ketika saya memperbarui statistik pada CurrencyShareds bagian dengan perubahan "histogram buruk" dan kardinalitas dihitung dengan benar

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

Dan info statistik untuk "[CurrencyShareds] ini. Dari statistik dengan id 1" dengan peringatan tentang histogram, yang terlihat bagus untuk saya ...

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

dan info untuk indeks kedua:

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
LeMaciek
sumber

Jawaban:

10

Berdasarkan histogram Anda, saya dapat mem - repro masalah ini pada 2017 CU6. Saya tidak akan mengatakan bahwa Anda melakukan sesuatu yang salah. Sebaliknya, ada yang salah dengan estimasi kardinalitas. Inilah yang saya dapatkan sebelum memasukkan baris:

masukkan deskripsi gambar di sini

Perkiraan kardinalitas terakhir turun sedikit setelah memasukkan satu baris:

masukkan deskripsi gambar di sini

Anda memiliki repro yang cukup sederhana di sini sehingga saran saya adalah mengajukan umpan balik produk atau membuka tiket dukungan dengan Microsoft. Saya dapat menemukan beberapa solusi yang berfungsi pada data sampel Anda dan salah satunya mungkin dapat diterima untuk Anda.

  1. Jatuhkan indeks unik CurrencyShareds.Id. Saya tidak dapat menjalankan repro tanpa indeks yang unik. Tabelnya kecil, jadi mungkin Anda bisa bertahan tanpa indeks. Tentu saja, Anda mungkin memiliki alasan yang sangat bagus untuk menyimpannya.
  2. Wujudkan hasil dari join menjadi tabel temp. Berdasarkan pertanyaan Anda, penting untuk mendapatkan estimasi yang masuk akal pada langkah ini sehingga kueri yang lebih besar berkinerja baik. Tabel temp adalah salah satu cara untuk mewujudkannya.
  3. Gunakan warisan CE. Saya tidak bisa mendapatkan masalah untuk mereproduksi dengannya. Tentu saja, ini mungkin memiliki konsekuensi negatif pada sisa permintaan Anda.
  4. Menipu pengoptimal kueri dengan kode konyol. Misalnya, dalam pengujian saya penulisan ulang berikut berfungsi dengan baik:

.

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

Saya menduga bahwa ini berfungsi karena CE tampaknya menggunakan densitas daripada histogram. Penulisan ulang serupa lainnya mungkin memiliki efek yang sama. Tidak ada jaminan bahwa jenis kueri akan terus berfungsi dengan baik di masa mendatang. Itu sebabnya Anda harus menghubungi Microsoft untuk meningkatkan kemungkinan bahwa suatu hari suatu perbaikan untuk masalah Anda akan membuatnya menjadi produk yang dirilis.

Joe Obbish
sumber
8

Ok, saya harap saya mengerti sekarang - jadi ini kasus kami

Diberikan

  1. Tabel referensi (CurrencyShareds) dengan ~ 100 baris, tetapi id besar, dan nilai maks, sangat berbeda - min: 119.762.190.797.406.464 vs maks: 977.955.748.426.318.592
  2. Tabel (Lampiran) yang memiliki FK sederhana untuk CurrencyShared, tetapi hanya beberapa Mata Uang yang digunakan - Anda dapat melihat bahwa histogram untuk IX_FK_Amount_TransactionCurrency mendaftar 5 id - dan yang penting hanya id "rendah", karena yang lain tidak digunakan.

Ketika semua statistik diperbarui maka

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

Maka selektivitas dihitung untuk bergabung baik-baik saja, karena 100 * 107.131 * 0,01 = 107.131

Ketika statistik untuk currencyshared tidak diperbarui, maka

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

Selektivitas turun secara dramatis, dan karenanya perkiraan jumlah baris gabungan adalah 1.

Ketika histogram berubah

Setelah saya menambahkan satu baris ke lampiran yang refrences CurrencyShared dengan id tinggi, maka hasilnya histogram untuk IX_FK_Amount_TransactionCurrency berubah menjadi

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

Dengan histogram ini masalahnya hilang, kini menambahkan baris baru ke bagan arus tidak menyebabkan penurunan dramatis dalam perkiraan kardinalitas.

Mengapa demikian?

Saya menduga ini adalah bagaimana algoritma estimasi histogram kasar bekerja di sql2014 +, dan saya mendasarkan dugaan saya pada posting hebat ini https://www.sqlshack.com/join-estimation-internals/

Estimasi Histogram Kasar adalah algoritma baru dan kurang didokumentasikan, bahkan dalam hal konsep umum. Diketahui bahwa alih-alih menyelaraskan histogram langkah demi langkah, justru menyelaraskannya dengan batas histogram minimum dan maksimum. Metode ini berpotensi menimbulkan lebih sedikit kesalahan CE (tidak selalu, karena kami ingat ini hanya model).

Hanya untuk memperjelas semuanya - mengapa kita memiliki id aneh seperti ini di currencyshareds?

Ini cukup sederhana - id kami secara global unik dan sebagian didasarkan pada timestamp (implementasi berdasarkan kepingan salju ). Mata uang yang paling umum ditambahkan pada awal aplikasi beberapa tahun yang lalu, dan hanya sedikit yang benar-benar digunakan dalam produksi, itu sebabnya dalam histogram hanya ada yang dengan id "rendah".

Masalah muncul pada lingkungan pengujian kami, di mana beberapa tes otomatis mulai menambahkan mata uang uji, menyebabkan beberapa kueri dieksekusi lebih lama atau ...

Bagaimana cara mengatasi masalah?

Kami akan memperbarui statistik untuk tabel referensi tersebut (kami mungkin memiliki masalah yang sama dengan tabel data referensi serupa lainnya) lebih sering - tabel tersebut berukuran kecil sehingga memperbarui statistik bukanlah masalah

Pelajaran yang Dipetik

  • Statistik terkini sangat penting !!!
  • kolom identitas lama yang polos tidak akan menyebabkan masalah ini :)
LeMaciek
sumber
Mengenai penyelarasan kasar: sqlperformance.com/2018/11/sql-optimizer/…
Paul White 9