Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

Bitmap Mode Batch di SQL Server

Latar Belakang

Dalam mode baris tradisional rencana eksekusi, SQL Server dapat memperkenalkan operator Bitmap sebagai bagian dari melakukan pengurangan semi-gabungan awal sebelum hash paralel atau gabung gabung. Bitmap dibangun dari input build, dan digunakan untuk memfilter baris pada input probe sebelum mencapai join. Saya telah menulis tentang mode baris bitmap sebelumnya dan juga tercakup dalam dokumentasi.

Artikel ini tentang mode batch bitmap, yang memiliki implementasi yang sangat berbeda. Ada peningkatan besar sejak penampilan pertama mesin eksekusi mode batch di SQL Server 2012. Detail yang diberikan di sini berlaku untuk SQL Server 2017 — versi terbaru yang dirilis pada saat penulisan. Fitur khusus untuk versi sebelumnya akan disebutkan sebaris seiring berjalannya waktu.

Pengoptimal Kueri

Satu-satunya operator join yang dapat berjalan dalam mode batch adalah hash join. Pengoptimal kueri memutuskan apakah gabungan hash mode batch (serial atau paralel) harus memiliki bitmap atau tidak. Pengoptimal menilai potensi kegunaan bitmap dengan menghitung selektivitas dari semi join hipotetis dari input hash join pada kunci join.

Semi join masuk akal, karena fungsi penyaringan bitmap adalah untuk menghapus baris dari sisi probe yang tidak ada di sisi build. Jika estimasi selektivitas dari semi join adalah 0,75 atau kurang, pengoptimal menganggapnya bermanfaat menggunakan filter bitmap mode batch. Dengan kata lain, bitmap ditentukan jika perhitungan semi join menunjukkan bahwa 25% atau lebih dari baris sisi probe akan dihilangkan oleh bitmap.

Selektivitas semi join yang tepat hanya digunakan untuk menentukan apakah hash join harus memiliki bitmap atau tidak. Perkiraan selektivitas sisi probe (terlihat sebagai efek pada perkiraan kardinalitas) dimodifikasi untuk mencerminkan fakta bahwa bitmap umumnya tidak sempurna dalam menghapus baris yang tidak memenuhi syarat. Hal ini terutama terjadi ketika bitmap diimplementasikan menggunakan filter Bloom, yang dapat menghasilkan positif palsu (baris sisi-penyelidik yang lolos filter, namun tidak bergabung dengan sisi build).

Pembulatan selektivitas

Pengoptimal memperhitungkan ketidakpastian ini dengan membulatkan selektivitas semi-gabungan menjadi pangkat sepuluh. Ini dilakukan dengan mengambil logaritma basis-10 sebelum pembulatan. Misalnya, selektivitas setengah gabungan sebesar 0,316 memberikan log10 nilai pecahan di bawah -0,5, yang dibulatkan ke bawah menjadi -1. Selektivitas sisi probe yang dihasilkan adalah 10 =0,1. Sebaliknya, selektivitas semi join sebesar 0,317 memberikan log10 nilai tepat di atas -0,5, yang dibulatkan menjadi nol. Oleh karena itu, selektivitas sisi probe adalah 10 =1 (semua baris lulus). Kemungkinan selektivitas bitmap sisi penyelidikan yang dihasilkan dari rangkaian perhitungan ini adalah 1, 0,1, 0,01, 0,001 dan seterusnya. Perhatikan bahwa bitmap masih dapat digunakan saat perkiraan selektivitas dibulatkan ke atas 1 (semua baris lulus predikat).

Estimasi operator dan kardinalitas

Tidak ada Bitmap yang terpisah operator untuk bergabung dengan mode batch. Sebagai gantinya, operator hash join memiliki Pembuat Bitmap properti (diatur ke true), atau properti tidak ada (tidak disetel ke false). Perbedaan antara eksekusi mode baris dan mode batch ini membuat lebih mudah untuk melihat apakah bitmap sedang dibuat, tetapi lebih akurat mencerminkan proses yang mendasarinya:Dalam eksekusi mode baris, Bitmap operator mengisi bitmap saat baris mengalir melaluinya, satu per satu, sebelum mencapai input hash join build. Dengan kata lain, tabel bitmap dan hash dibangun secara bersamaan di bawah eksekusi mode baris. Dalam mode batch, tabel hash dibuat sepenuhnya sebelum bitmap dibuat (lebih lanjut tentang ini segera).

Pengoptimal kueri tidak membuat pilihan berbasis biaya tentang posisi filter bitmap mode batch di sisi pemeriksaan gabungan hash. Ini hanya mengasumsikan bahwa selektivitas bitmap akan berlaku untuk semua operator anak di sisi probe. Pada kenyataannya, bitmap hanya didorong ke bawah sisi probe setelah satu rencana eksekusi akhir telah dipilih oleh pengoptimal. Jika bitmap tidak dapat didorong sepenuhnya ke operator daun, perkiraan kardinalitas akan terlihat agak aneh. Ini adalah pertukaran yang dapat ditingkatkan di masa mendatang.

Mesin Eksekusi

Sementara pengoptimal memutuskan apakah bitmap mode batch gabungan hash harus digunakan atau tidak, mesin eksekusi mode batch memutuskan jenis bitmap untuk digunakan saat runtime. Keputusan ini diinformasikan oleh informasi statistik yang dikumpulkan tentang kunci gabungan sisi build selama pembuatan tabel hash. Seperti yang disebutkan sebelumnya, berbeda dengan eksekusi mode baris, hash mode batch bergabung sepenuhnya untuk membangun tabel hash terlebih dahulu, sebelum melewati tabel hash secara terpisah dilakukan untuk membangun bitmap.

Bitmap Sederhana

Ada dua tipe utama dari batch mode hash join bitmap. sederhana bitmap berisi satu bit untuk masing-masing rentang nilai sisi build yang berdekatan. Misalnya, bitmap sederhana satu byte mampu menunjukkan apakah ada delapan nilai sisi build yang berdekatan atau tidak. Nilai 0 sampai 7 inklusif dapat dikodekan ke dalam bitmap dengan mengatur bit yang sesuai. Nilai 5 akan menetapkan bit 5, yang memiliki nilai posisi 2. Kita dapat mengkodekan himpunan {1, 5, 7} sebagai 2 + 2 + 2 =2 + 32 + 128 =162 =101000102 . Rentang nilai yang tidak dimulai dari nol dapat dikodekan dengan cara yang sama dengan mengimbangi semua nilai dengan nilai minimum yang ada dalam himpunan (yang kita ketahui dari statistik tabel hash).

Bitmap sederhana memiliki keuntungan menyimpan tepat informasi tentang nilai sisi build yang benar-benar ada, dengan biaya yang membutuhkan memori yang sebanding dengan rentang nilai yang ada.

Bitmap Kompleks

Jenis bitmap yang kedua adalah filter Bloom. Ini menetapkan satu atau lebih bit dalam struktur bitmap sesuai dengan hasil penerapan satu atau lebih fungsi hash ke setiap nilai sisi build. Kami menguji kecocokan dengan menerapkan fungsi hash yang sama untuk setiap nilai sisi probe. Jika salah satu fungsi hash mengidentifikasi bit yang tidak disetel, kami dapat yakin bahwa nilai probe saat ini tidak muncul di sisi build.

Karena filter Bloom adalah struktur probabilistik, kami mungkin tidak memfilter beberapa nilai probe yang tidak memiliki kecocokan sisi build (positif palsu), tetapi kami tidak akan pernah memfilter nilai yang ada (negatif palsu). Dengan kata lain, filter Bloom memberi tahu kita "mungkin cocok" atau "pasti tidak cocok". Tingkat positif palsu dapat dikurangi baik dengan menggunakan lebih banyak bit per kunci (bitmap yang lebih besar) atau lebih banyak fungsi hash. Agar jelas, filter Bloom mungkin menghasilkan pemfilteran yang tepat, tetapi mungkin juga tidak.

Filter Bloom menghadirkan alternatif yang hemat ruang dan waktu ketika bitmap sederhana tidak layak karena kebutuhan ruang. Implementasi mode batch SQL Server dari filter Bloom dioptimalkan untuk arsitektur cache CPU modern dan secara internal dikenal sebagai bitmap kompleks . Bitmap kompleks telah mendukung beberapa kolom gabungan dan semua tipe data mode batch sejak SQL Server 2014.

Pilihan Bitmap

Apakah SQL Server memilih sederhana atau kompleks (Filter mekar) bitmap bergantung pada rentang nilai sisi build (dari statistik tabel hash). Ada peringatan penting untuk kata "rentang" di sana, yang akan dijelaskan di bagian selanjutnya. Sementara itu, beginilah cara mesin eksekusi memilih jenis bitmap:

  1. Sebuah bitmap kecil sederhana digunakan ketika rentang nilai adalah 2 (8.388.608) atau kurang. Ini adalah jumlah bit dalam 1 MB.
  2. Bila rentang nilai lebih dari 2 tetapi kurang dari atau sama dengan 2 (8MB), mesin eksekusi memilih antara bitmap sederhana yang besar dan bitmap kompleks dengan menghitung memori yang diperlukan untuk setiap opsi dan memilih yang lebih kecil. Bitmap sederhana yang besar dapat berukuran hingga 8 MB. Ukuran bitmap kompleks tergantung pada jumlah bit per kunci yang diperlukan untuk mewakili data secara memadai. Nilai yang lebih berbeda biasanya berarti bitmap kompleks yang lebih besar.
  3. Jika rentang nilai lebih dari 2 bit, bitmap kompleks digunakan.

Tentang rentang nilai

Rentang nilai yang dirujuk di atas didasarkan pada biner internal representasi datanya. Misalnya, smallint nilai 128 dan 255 dapat direpresentasikan sebagai 0x0080 dan 0x00FF , memberikan rentang 0x7F (127) nilai biner. Rentang ini akan bekerja dengan baik dengan bitmap kecil sederhana.

Sebaliknya, datetime nilai “1900-01-01” dan “1900-01-02” dapat direpresentasikan dalam 8 byte sebagai 0x0000000100000000 dan 0x0000000200000000 (empat byte untuk hari dan empat byte untuk kutu setelah tengah malam). Representasi tersegmentasi ini memberikan rentang biner 0x0100000000 (4.294.967.296) untuk dua nilai contoh tersebut, yang terlalu besar untuk dimasukkan ke dalam bitmap sederhana (bahkan yang besar). Tipe data dengan representasi biner yang kompleks (misalnya pertukaran byte) biasanya tidak akan berfungsi dengan baik dengan bitmap sederhana.

Komplikasi lebih lanjut adalah bahwa data mode batch dinormalisasi — dikonversi ke tata letak biner yang berfungsi baik dengan instruksi vektor — dan selalu berukuran 64 bit. Nilai yang tidak dapat ditampung dalam 64 bit disimpan "di luar baris", dengan pointer 64-bit dalam baris. Layout biner ini tidak sama dengan yang dilaporkan oleh konversi T-SQL ke tipe biner.

Namun demikian, tata letak yang dinormalisasi cukup mirip untuk tipe integer (mis. integer dan bigint ) bahwa bitmap sederhana masih berguna untuk rentang tipe data ini. Jenis lain dengan representasi biner seperti bilangan bulat (mis. money dan date ) juga cocok.

Satu contoh lagi:Satu set integer nilai dalam rentang 1 hingga 8.388.608 akan hanya muat dalam bitmap sederhana kecil 1MB, menggunakan satu bit per kemungkinan nilai integer dalam kisaran. Rentang mungkin memiliki offset tetap, jadi rentang bilangan bulat 10.000.000 hingga 18.388.607 juga cocok (dengan offset sepuluh juta). Perhatikan bahwa nomor nilai yang ada tidak masalah, hanya kisarannya. Dua nilai 0 dan 8.388.607 akan mengisi rentang bitmap sederhana yang kecil serta kumpulan semua nilai yang mungkin di antara kedua ekstrem tersebut.

Tabel Rentang

Saat mesin eksekusi mode batch memutuskan untuk membuat sederhana besar bitmap atau kompleks bitmap untuk hash join, itu juga membangun tabel rentang. Itu tidak buat tabel rentang untuk kecil bitmap sederhana.

Tabel rentang adalah struktur 128KB ukuran tetap yang terdiri dari 8.192 pasang nilai 8-byte yang menentukan rentang nilai (rendah, tinggi) yang ada dalam tabel hash. Tabel rentang dapat dibuat pada tipe data apa pun yang kompatibel dengan eksekusi mode batch. Selama pemindaian tabel hash yang telah selesai, setiap kumpulan data digunakan untuk mengisi bitmap dan tabel jangkauan.

Untuk setiap nilai dalam batch, fungsi hash digunakan untuk menemukan bucket (pasangan nilai rentang) di tabel rentang. Jika bucket saat ini tidak digunakan, nilai disimpan dalam nilai 8 byte rendah dan tinggi. Jika ember sudah digunakan, ember berikutnya akan diisi (dan seterusnya, sampai ember kosong ditemukan).

Jika tabel rentang menjadi sepertiga penuh (2.730 dari 8.192 ember digunakan), entri yang digunakan disalin, rentang ember digandakan, kemudian nilai yang disimpan dimasukkan kembali dengan cara yang sama seperti sebelumnya (meskipun fungsi hash memperhitungkan ukuran ember baru). Setiap ember yang tumpang tindih digabung, dan proses penggandaan berlanjut hingga jumlah ember yang digunakan turun di bawah 2.730. Misalnya, dua ember yang awalnya berisi 'rentang' (1-1) dan (2-2) dapat bergabung menjadi satu ember rentang (1-2) setelah rentang pertama berlipat ganda.

Setelah semua kumpulan data tabel hash telah diproses ke dalam tabel rentang, penggabungan bucket terakhir dilakukan, kemudian quicksort di tempat menempatkan bucket dalam urutan nilai. Hal ini memungkinkan pencarian biner untuk menemukan ember rentang yang diberi nilai minat tertentu.

Hasil bersih dari semua aktivitas ini adalah menghasilkan satu set hingga 2.730 rentang berbeda yang menjelaskan data dalam tabel hash (selain bitmap sederhana atau kompleks yang besar).

Menggunakan Tabel Rentang

Tabel rentang digunakan ketika filter bitmap gabungan hash didorong ke bawah ke operator pemindaian penyimpanan kolom sisi penyelidikan. Setiap segmen columnstore memiliki metadata katalog tentang nilai data minimum dan maksimum yang ada di segmen tersebut. Mesin eksekusi dapat menggunakan informasi ini untuk mencari biner pada tabel rentang bitmap untuk kecocokan. Jika tidak ada kecocokan yang ditemukan, mesin eksekusi dapat melewati segmen sepenuhnya.

Optimalisasi runtime ini juga terjadi untuk read-ahead, sehingga engine bahkan dapat menghindari membaca segmen ke dalam memori yang diketahuinya akan dihilangkan oleh filter tabel rentang. Segmen apa pun yang tidak dihilangkan oleh tabel rentang masih difilter menggunakan bitmap. Kombinasi ini menghasilkan jumlah maksimum baris yang dihilangkan sedini mungkin.

Meskipun tabel rentang tidak dibuat untuk bitmap sederhana yang kecil, struktur itu juga dapat digunakan untuk mencapai eliminasi segmen karena rentang nilai diketahui (termasuk offset apa pun). Ini cukup kecil untuk membuatnya tidak berguna untuk mempartisinya menjadi sub-rentang menggunakan tabel rentang.

Ketika bitmap tidak didorong ke dalam pemindaian columnstore, itu masih dapat dievaluasi sebagai filter mode batch biasa untuk mencapai pengurangan semi-join sebelum hash bergabung. Ini jauh lebih tidak efisien daripada eliminasi segmen atau pemfilteran selama pemindaian columnstore, tetapi masih lebih baik daripada pemfilteran pada hash join itu sendiri.

Bitmap dan Data Terkompresi

Menerapkan bitmap mode batch gabungan hash ke data penyimpanan kolom sebagai bagian dari pemindaian dapat menghasilkan kinerja yang sangat baik, tetapi hal itu membutuhkan data segmen yang tidak murni untuk didekompresi sebelum bitmap dapat diterapkan. Dekompresi ini dapat dilakukan secara efisien menggunakan instruksi SIMD, tetapi ini masih merupakan pekerjaan ekstra.

SQL Server 2016 memperkenalkan kemampuan untuk membuat bitmap untuk predikat umum pada data segmen yang disandikan kamus. Predikat dievaluasi terhadap entri kamus untuk menghasilkan baru bitmap kecil dengan setiap set bit menunjukkan entri kamus yang memenuhi predikat. Menerapkan bitmap ini bisa sangat cepat, terutama jika bitmap cocok dalam satu register SIMD. SQL Server masih dapat menggunakan SIMD jika bitmap tidak cocok, tetapi mengumpulkan bit dari bitmap dalam memori sedikit kurang efisien dibandingkan kasus dalam register.

Pengoptimalan 2016 ini dapat diterapkan ke apa saja predikat didorong ke dalam pemindaian columnstore, termasuk 'predikat' bitmap yang dibuat oleh gabungan hash hulu. Agar jelas, SQL Server mengambil bitmap hash join dan membuat bitmap baru (jauh lebih kecil) menggunakan entri kamus. Bitmap baru ini diterapkan ke data segmen sebelum dekompresi. Pengoptimalan dapat dipantau dengan column_store_expression_filter_bitmap_set peristiwa yang diperluas . Saat bitmap kamus digunakan, anggota acara filter_on_compressed_data_type anggota akan terisi. Biasanya ini akan berisi nilai RAWBITMAP . Ada optimasi lebih lanjut untuk mengonversi bitmap kamus terkompresi ke filter perbandingan jika bitmap kamus mewakili rentang nilai tunggal yang berdekatan. Dalam hal ini Anda akan melihat sesuatu selain RAWBITMAP (mis. LTGT untuk kurang dari/lebih besar dari perbandingan).

Acara yang Diperpanjang dan Tanda Pelacakan

Kemampuan umum untuk mengkompilasi filter push-down (termasuk bitmap yang dihasilkan oleh gabungan hash mode batch) pada pemindaian kolomstore ke dalam bitmap dapat dinonaktifkan dengan tanda pelacakan tingkat sesi 9361. Pengoptimalan bitmap data terkompresi khusus dapat dinonaktifkan dengan sesi -level trace flag 9362. Konversi bitmap kamus dengan satu rentang berdekatan ke filter perbandingan dapat dinonaktifkan dengan trace flag 9363. Sayangnya, tidak ada flag trace build-ritel yang melaporkan pesan informasi tentang bitmap mode batch atau filter push-down kompilasi.

Ada beberapa kejadian tambahan yang menghasilkan informasi tentang bitmap mode gabungan hash. Yang paling berguna adalah:

  • query_execution_column_store_segment_scan_started
  • query_execution_column_store_segment_scan_finished
  • column_store_expression_filter_bitmap_set
  • column_store_segment_eliminate

Saat bitmap mode batch gabungan hash didorong ke bawah ke pemindaian columnstore, peristiwa "dimulai" melaporkan BITMAP_SIMPLE atau BITMAP_COMPLEX sebagai filter_type . Itu tidak membedakan antara bitmap sederhana kecil dan besar, juga tidak melaporkan apa pun tentang tabel rentang. Metadata peristiwa yang diperluas memang berisi nilai lain untuk column_store_filter_type yang menyertakan BITMAP_SIMPLE_LARGE antara lain, tetapi acara yang diperluas saat ini tidak menghasilkan output ini ketika bitmap sederhana yang besar digunakan. Mungkin ini akan diperbaiki di rilis mendatang.

Bendera jejak global 646 dapat digunakan untuk melaporkan informasi tentang penghapusan segmen yang diaktifkan oleh tabel rentang (atau bitmap kecil sederhana). Ini melaporkan informasi serupa ke segmen menghilangkan acara diperpanjang. Semua tanda jejak yang disebutkan di bagian ini tidak didokumentasikan dan tidak didukung.

Pemikiran Terakhir

Bitmap mode batch bisa sangat efektif jika tipe data yang tepat (maks 64 bit dan seperti bilangan bulat) digunakan dan bitmap dapat ditekan ke pemindaian penyimpanan kolom, terutama jika data segmen menggunakan kompresi RLE (penyimpanan murni), atau jika bitmap dapat dikompilasi menjadi bitmap lain pada data kamus.

Mungkin bagus jika rencana eksekusi melaporkan informasi yang lebih rinci tentang hash join bitmap — setidaknya untuk mengatakan jenis bitmap apa yang dibuat. Karena itu, kami hanya memiliki Pembuat Bitmap properti, dan beberapa acara tambahan untuk dikerjakan. Hal ini membuat analisis rencana terperinci sedikit lebih sulit daripada yang seharusnya, mengingat peningkatan kinerja yang sangat besar yang dapat diwujudkan dengan memanfaatkan semua pengoptimalan cerdas yang dibangun ke dalam mesin eksekusi untuk data penyimpanan kolom dan gabungan hash mode batch.

Demo, ilustrasi, dan diskusi lebih lanjut tentang poin utama yang dibahas dalam artikel ini tersedia di situs pribadi saya di Demo Bitmap Mode Batch.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. T-SQL Bagaimana cara membuat tabel secara dinamis dalam prosedur tersimpan?

  2. Setara terbaik untuk IsInteger di SQL Server

  3. Tips Cepat untuk Memperbaiki dan Memulihkan Database SQL Tanpa Cadangan

  4. Bagaimana cara menghapus semua karakter non-abjad dari string di SQL Server?

  5. SQL Server - temukan kemunculan ke-n dalam sebuah string