Bagaimana jumlah langkah histogram diputuskan dalam Statistik di SQL Server?
Mengapa dibatasi hingga 200 langkah meskipun kolom kunci saya memiliki lebih dari 200 nilai yang berbeda? Apakah ada faktor penentu?
Demo
Definisi skema
CREATE TABLE histogram_step
(
id INT IDENTITY(1, 1),
name VARCHAR(50),
CONSTRAINT pk_histogram_step PRIMARY KEY (id)
)
Memasukkan 100 catatan ke meja saya
INSERT INTO histogram_step
(name)
SELECT TOP 100 name
FROM sys.syscolumns
Memperbarui dan memeriksa statistik
UPDATE STATISTICS histogram_step WITH fullscan
DBCC show_statistics('histogram_step', pk_histogram_step)
Langkah histogram:
+--------------+------------+---------+---------------------+----------------+
| RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | AVG_RANGE_ROWS |
+--------------+------------+---------+---------------------+----------------+
| 1 | 0 | 1 | 0 | 1 |
| 3 | 1 | 1 | 1 | 1 |
| 5 | 1 | 1 | 1 | 1 |
| 7 | 1 | 1 | 1 | 1 |
| 9 | 1 | 1 | 1 | 1 |
| 11 | 1 | 1 | 1 | 1 |
| 13 | 1 | 1 | 1 | 1 |
| 15 | 1 | 1 | 1 | 1 |
| 17 | 1 | 1 | 1 | 1 |
| 19 | 1 | 1 | 1 | 1 |
| 21 | 1 | 1 | 1 | 1 |
| 23 | 1 | 1 | 1 | 1 |
| 25 | 1 | 1 | 1 | 1 |
| 27 | 1 | 1 | 1 | 1 |
| 29 | 1 | 1 | 1 | 1 |
| 31 | 1 | 1 | 1 | 1 |
| 33 | 1 | 1 | 1 | 1 |
| 35 | 1 | 1 | 1 | 1 |
| 37 | 1 | 1 | 1 | 1 |
| 39 | 1 | 1 | 1 | 1 |
| 41 | 1 | 1 | 1 | 1 |
| 43 | 1 | 1 | 1 | 1 |
| 45 | 1 | 1 | 1 | 1 |
| 47 | 1 | 1 | 1 | 1 |
| 49 | 1 | 1 | 1 | 1 |
| 51 | 1 | 1 | 1 | 1 |
| 53 | 1 | 1 | 1 | 1 |
| 55 | 1 | 1 | 1 | 1 |
| 57 | 1 | 1 | 1 | 1 |
| 59 | 1 | 1 | 1 | 1 |
| 61 | 1 | 1 | 1 | 1 |
| 63 | 1 | 1 | 1 | 1 |
| 65 | 1 | 1 | 1 | 1 |
| 67 | 1 | 1 | 1 | 1 |
| 69 | 1 | 1 | 1 | 1 |
| 71 | 1 | 1 | 1 | 1 |
| 73 | 1 | 1 | 1 | 1 |
| 75 | 1 | 1 | 1 | 1 |
| 77 | 1 | 1 | 1 | 1 |
| 79 | 1 | 1 | 1 | 1 |
| 81 | 1 | 1 | 1 | 1 |
| 83 | 1 | 1 | 1 | 1 |
| 85 | 1 | 1 | 1 | 1 |
| 87 | 1 | 1 | 1 | 1 |
| 89 | 1 | 1 | 1 | 1 |
| 91 | 1 | 1 | 1 | 1 |
| 93 | 1 | 1 | 1 | 1 |
| 95 | 1 | 1 | 1 | 1 |
| 97 | 1 | 1 | 1 | 1 |
| 99 | 1 | 1 | 1 | 1 |
| 100 | 0 | 1 | 0 | 1 |
+--------------+------------+---------+---------------------+----------------+
Seperti yang bisa kita lihat ada 53 langkah dalam histogram.
Sekali lagi memasukkan beberapa ribu catatan
INSERT INTO histogram_step
(name)
SELECT TOP 10000 b.name
FROM sys.syscolumns a
CROSS JOIN sys.syscolumns b
Memperbarui dan memeriksa statistik
UPDATE STATISTICS histogram_step WITH fullscan
DBCC show_statistics('histogram_step', pk_histogram_step)
Sekarang langkah histogram dikurangi menjadi 4 langkah
+--------------+------------+---------+---------------------+----------------+
| RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | AVG_RANGE_ROWS |
+--------------+------------+---------+---------------------+----------------+
| 1 | 0 | 1 | 0 | 1 |
| 10088 | 10086 | 1 | 10086 | 1 |
| 10099 | 10 | 1 | 10 | 1 |
| 10100 | 0 | 1 | 0 | 1 |
+--------------+------------+---------+---------------------+----------------+
Sekali lagi memasukkan beberapa ribu catatan
INSERT INTO histogram_step
(name)
SELECT TOP 100000 b.name
FROM sys.syscolumns a
CROSS JOIN sys.syscolumns b
Memperbarui dan memeriksa statistik
UPDATE STATISTICS histogram_step WITH fullscan
DBCC show_statistics('histogram_step', pk_histogram_step)
Sekarang langkah histogram dikurangi menjadi 3 langkah
+--------------+------------+---------+---------------------+----------------+
| RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | AVG_RANGE_ROWS |
+--------------+------------+---------+---------------------+----------------+
| 1 | 0 | 1 | 0 | 1 |
| 110099 | 110097 | 1 | 110097 | 1 |
| 110100 | 0 | 1 | 0 | 1 |
+--------------+------------+---------+---------------------+----------------+
Dapatkah seseorang memberi tahu saya bagaimana langkah-langkah ini diputuskan?
sql-server
statistics
P ரதீப்
sumber
sumber
Jawaban:
Saya akan membatasi posting ini untuk membahas statistik satu kolom karena sudah cukup panjang dan Anda tertarik pada bagaimana SQL Server memasukkan data ke dalam langkah-langkah histogram. Untuk statistik multi-kolom histogram hanya dibuat pada kolom terkemuka.
Ketika SQL Server menentukan bahwa pembaruan statistik diperlukan itu memulai permintaan tersembunyi yang membaca semua data tabel atau sampel data tabel. Anda dapat melihat pertanyaan ini dengan acara yang diperpanjang. Ada fungsi yang disebut
StatMan
dalam SQL Server yang terlibat dengan membuat histogram. Untuk objek statistik sederhana setidaknya ada dua jenisStatMan
kueri yang berbeda (ada kueri yang berbeda untuk pembaruan stat cepat dan saya menduga bahwa fitur statistik tambahan pada tabel yang dipartisi juga menggunakan kueri yang berbeda).Yang pertama hanya mengambil semua data dari tabel tanpa penyaringan. Anda dapat melihat ini ketika tabel sangat kecil atau Anda mengumpulkan statistik dengan
FULLSCAN
opsi:SQL Server mengambil ukuran sampel otomatis berdasarkan ukuran tabel (saya pikir itu adalah jumlah baris dan halaman dalam tabel). Jika tabel terlalu besar maka ukuran sampel otomatis turun di bawah 100%. Inilah yang saya dapatkan untuk tabel yang sama dengan baris 1M:
TABLESAMPLE
adalah didokumentasikan tetapi Statman dan step_direction tidak. di sini SQL Server sampel sekitar 66,6% dari data dari tabel untuk membuat histogram. Artinya, Anda bisa mendapatkan jumlah langkah histogram yang berbeda saat memperbarui statistik (tanpaFULLSCAN
) pada data yang sama. Saya belum pernah mengamati ini dalam praktik tetapi saya tidak melihat mengapa itu tidak mungkin.Mari kita jalankan beberapa tes pada data sederhana untuk melihat bagaimana statistik berubah seiring waktu. Di bawah ini adalah beberapa kode tes yang saya tulis untuk memasukkan bilangan bulat berurutan ke dalam tabel, mengumpulkan statistik setelah setiap sisipan, dan menyimpan informasi tentang statistik ke dalam tabel hasil. Mari kita mulai dengan memasukkan 1 baris sekaligus hingga 10.000. Test bed:
Untuk data ini jumlah langkah histogram dengan cepat meningkat menjadi 200 (pertama-tama menyentuh jumlah maksimum langkah dengan 397 baris), tetap pada 199 atau 200 hingga 1485 baris ada di tabel, kemudian perlahan-lahan menurun hingga histogram hanya memiliki 3 atau 4 Langkah. Berikut adalah grafik dari semua data:
Begini histogramnya untuk baris 10rb:
Apakah masalah bahwa histogram hanya memiliki 3 langkah? Sepertinya informasi dipertahankan dari sudut pandang kami. Perhatikan bahwa karena datatype adalah INTEGER kita bisa mengetahui berapa banyak baris dalam tabel untuk setiap bilangan bulat dari 1 - 10.000. Biasanya SQL Server juga bisa mengetahuinya, meskipun ada beberapa kasus di mana ini tidak cukup berhasil . Lihat posting SE ini untuk contohnya.
Menurut Anda apa yang akan terjadi jika kami menghapus satu baris dari tabel dan memperbarui statistik? Idealnya kita akan mendapatkan langkah histogram lain untuk menunjukkan bahwa integer yang hilang tidak lagi ada dalam tabel.
Itu sedikit mengecewakan. Jika kami membuat histogram dengan tangan, kami akan menambahkan langkah untuk setiap nilai yang hilang. SQL Server menggunakan algoritme tujuan umum sehingga untuk beberapa set data, kami mungkin dapat membuat histogram yang lebih cocok daripada kode yang digunakannya. Tentu saja, perbedaan praktis antara mendapatkan 0 atau 1 baris dari tabel sangat kecil. Saya mendapatkan hasil yang sama ketika menguji dengan 20.000 baris yang masing-masing bilangan bulat memiliki 2 baris dalam tabel. Histogram tidak mendapatkan langkah saat saya menghapus data.
Jika saya menguji dengan 1 juta baris dengan setiap bilangan bulat memiliki 100 baris dalam tabel, saya mendapatkan hasil yang sedikit lebih baik, tetapi saya masih dapat membuat histogram yang lebih baik dengan tangan.
Histogram terakhir:
Mari kita uji lebih lanjut dengan integer berurutan tetapi dengan lebih banyak baris dalam tabel. Perhatikan bahwa untuk tabel yang terlalu kecil secara manual menentukan ukuran sampel tidak akan berpengaruh, jadi saya akan menambahkan 100 baris di setiap sisipan dan mengumpulkan statistik setiap kali hingga 1 juta baris. Saya melihat pola yang sama seperti sebelumnya, kecuali sekali saya mendapatkan 637300 baris dalam tabel saya tidak lagi sampel 100% dari baris dalam tabel dengan tingkat sampel default. Saat saya mendapatkan baris, jumlah langkah histogram meningkat. Mungkin ini karena SQL Server berakhir dengan lebih banyak kesenjangan dalam data karena jumlah baris yang tidak dicampuri dalam tabel meningkat. Saya tidak mencapai 200 langkah bahkan pada baris 1 M, tetapi jika saya terus menambahkan baris saya berharap saya akan sampai di sana dan akhirnya mulai turun kembali.
Sumbu X adalah jumlah baris dalam tabel. Ketika jumlah baris bertambah, baris-baris yang diambil sampel sedikit bervariasi dan tidak melebihi 650 ribu.
Sekarang mari kita lakukan beberapa tes sederhana dengan data VARCHAR.
Di sini saya memasukkan 200 angka (sebagai string) bersama dengan NULL.
Perhatikan bahwa NULL selalu mendapatkan langkah histogram sendiri ketika ditemukan dalam tabel. SQL Server bisa memberi saya tepat 201 langkah untuk menyimpan semua informasi tetapi tidak melakukan itu. Informasi teknis hilang karena '1111' antara '1' dan '2' misalnya.
Sekarang mari kita coba memasukkan karakter yang berbeda dan bukan hanya bilangan bulat:
Tidak ada perbedaan nyata dari tes terakhir.
Sekarang mari kita coba memasukkan karakter tetapi menempatkan angka yang berbeda dari setiap karakter di dalam tabel. Misalnya,
CHAR(11)
memiliki 1 baris,CHAR(12)
memiliki 2 baris, dll.Seperti sebelumnya saya masih belum mendapatkan persis 200 langkah histogram. Namun, banyak langkah memiliki
RANGE_ROWS
0.Untuk tes terakhir, saya akan memasukkan string acak 5 karakter di setiap loop dan mengumpulkan statistik setiap kali. Berikut kode string acak:
Berikut ini adalah grafik baris dalam tabel vs langkah-langkah histogram:
Perhatikan bahwa jumlah langkah tidak turun di bawah 100 setelah mulai naik dan turun. Saya telah mendengar dari suatu tempat (tetapi tidak dapat sumber sekarang) bahwa algoritma membangun histogram SQL Server menggabungkan langkah-langkah histogram karena kehabisan ruang untuk mereka. Jadi Anda bisa berakhir dengan perubahan drastis dalam jumlah langkah hanya dengan menambahkan sedikit data. Inilah satu contoh data yang menurut saya menarik:
Bahkan ketika pengambilan sampel dengan
FULLSCAN
, menambahkan satu baris dapat meningkatkan jumlah langkah dengan 10, tetap konstan, lalu menguranginya 2, lalu menguranginya dengan 3.Apa yang bisa kita simpulkan dari semua ini? Saya tidak bisa membuktikan semua ini, tetapi pengamatan ini tampaknya benar:
RANGE_ROWS
= 0.RANGE_HI_KEY
dalam tabel.DISTINCT_RANGE_ROWS
atauRANGE_ROWS
. Misalnya, 255 muncul beberapa kali untukRANGE_ROWS
danDISTINCT_RANGE_ROWS
untuk ujian akhir di sini.Kapan semua ini menjadi masalah? Ini masalah ketika kueri berkinerja buruk karena histogram yang tidak dapat mewakili distribusi data dengan cara pengoptimal kueri untuk membuat keputusan yang baik. Saya pikir ada kecenderungan untuk berpikir bahwa memiliki lebih banyak langkah-langkah histogram selalu lebih baik dan untuk itu ada kekhawatiran ketika SQL Server menghasilkan histogram pada jutaan baris atau lebih tetapi tidak menggunakan langkah-langkah tepat 200 atau 201 histogram. Namun, saya telah melihat banyak masalah statistik bahkan ketika histogram memiliki 200 atau 201 langkah. Kami tidak memiliki kendali atas berapa banyak langkah histogram yang dihasilkan SQL Server untuk objek statistik jadi saya tidak akan khawatir tentang hal itu. Namun, ada beberapa langkah yang bisa Anda ambil ketika Anda mengalami kueri berkinerja buruk yang disebabkan oleh masalah statistik. Saya akan memberikan gambaran yang sangat singkat.
Mengumpulkan statistik secara penuh dapat membantu dalam beberapa kasus. Untuk tabel yang sangat besar ukuran sampel otomatis mungkin kurang dari 1% dari baris dalam tabel. Terkadang hal itu dapat menyebabkan rencana yang buruk tergantung pada gangguan data di kolom. Dokumentasi Microsoft untuk CREATE STATISTICS dan UPDATE STATISTICS mengatakan:
Dalam beberapa kasus, membuat statistik yang difilter dapat membantu. Anda mungkin memiliki kolom dengan data miring dan banyak nilai berbeda yang berbeda. Jika ada nilai tertentu dalam data yang biasanya difilter pada Anda dapat membuat histogram statistik hanya untuk nilai-nilai umum tersebut. Pengoptimal kueri dapat menggunakan statistik yang ditentukan pada rentang data yang lebih kecil daripada statistik yang ditentukan pada semua nilai kolom. Anda masih tidak dijamin untuk mendapatkan 200 langkah dalam histogram, tetapi jika Anda membuat statistik yang difilter hanya pada satu nilai Anda akan langkah histogram nilai itu.
Menggunakan tampilan yang dipartisi adalah salah satu cara untuk secara efektif mendapatkan lebih dari 200 langkah untuk tabel. Misalkan Anda dapat dengan mudah membagi meja besar menjadi satu meja per tahun. Anda membuat
UNION ALL
tampilan yang menggabungkan semua tabel tahunan. Setiap tabel akan memiliki histogram sendiri. Perhatikan bahwa statistik inkremental baru yang diperkenalkan di SQL Server 2014 hanya memungkinkan pembaruan statistik menjadi lebih efisien. Pengoptimal kueri tidak akan menggunakan statistik yang dibuat per partisi.Ada banyak lagi tes yang dapat dijalankan di sini, jadi saya mendorong Anda untuk bereksperimen. Saya melakukan pengujian ini pada SQL Server 2014 express sehingga benar-benar tidak ada yang menghentikan Anda.
sumber