Saya ingat pernah membaca pada satu titik bahwa mengindeks bidang dengan kardinalitas rendah (jumlah nilai berbeda yang rendah) sebenarnya tidak layak dilakukan. Saya akui, saya tidak cukup tahu tentang cara kerja indeks untuk memahami mengapa demikian.
Jadi bagaimana jika saya memiliki tabel dengan 100 juta baris di dalamnya, dan saya memilih catatan dengan bidang bit 1? Dan katakanlah pada titik waktu mana pun, hanya ada sedikit record yang bidang bitnya adalah 1 (sebagai lawan 0). Apakah layak mengindeks bidang bit itu atau tidak? Mengapa?
Tentu saja saya bisa mengujinya dan mengecek rencana pelaksanaannya, dan saya akan melakukannya, tapi saya juga penasaran dengan teori di baliknya. Kapan kardinalitas penting dan kapan tidak?
sql-server
indexing
jeremcc
sumber
sumber
Jawaban:
Pertimbangkan apa itu indeks dalam SQL - dan indeks sebenarnya adalah potongan memori yang menunjuk ke potongan memori lainnya (yaitu, penunjuk ke baris). Indeks dipecah menjadi beberapa halaman sehingga bagian dari indeks dapat dimuat dan dikeluarkan dari memori tergantung pada penggunaan.
Saat Anda meminta satu set baris, SQL menggunakan indeks untuk menemukan baris lebih cepat daripada pemindaian tabel (melihat setiap baris).
SQL memiliki indeks berkerumun dan tidak berkerumun. Pemahaman saya tentang indeks berkerumun adalah bahwa mereka mengelompokkan nilai indeks yang serupa ke dalam halaman yang sama. Dengan cara ini ketika Anda meminta semua baris yang cocok dengan nilai indeks, SQL dapat mengembalikan baris tersebut dari halaman memori berkerumun. Inilah sebabnya mengapa mencoba untuk mengelompokkan indeks kolom GUID adalah ide yang buruk - Anda tidak mencoba untuk mengelompokkan nilai acak.
Saat Anda mengindeks kolom integer, indeks SQL berisi sekumpulan baris untuk setiap nilai indeks. Jika Anda memiliki rentang 1 hingga 10, maka Anda akan memiliki 10 penunjuk indeks. Bergantung pada berapa banyak barisnya, ini dapat dibuat halaman berbeda. Jika kueri Anda mencari indeks yang cocok dengan "1" dan kemudian di mana Nama berisi "Fred" (dengan asumsi kolom Nama tidak diindeks), SQL mendapatkan kumpulan baris yang cocok dengan "1" dengan sangat cepat, kemudian tabel memindai untuk menemukan sisanya.
Jadi apa yang sebenarnya dilakukan SQL adalah mencoba mengurangi set kerja (jumlah baris) yang harus diiterasi.
Saat Anda mengindeks bidang bit (atau beberapa rentang sempit), Anda hanya mengurangi kumpulan kerja dengan jumlah baris yang cocok dengan nilai itu. Jika Anda memiliki sejumlah kecil baris yang cocok, itu akan banyak mengurangi set kerja Anda. Untuk sejumlah besar baris dengan distribusi 50/50, ini mungkin memberi Anda sedikit keuntungan kinerja vs. menjaga indeks tetap mutakhir.
Alasan semua orang mengatakan untuk menguji adalah karena SQL berisi pengoptimal yang sangat pintar dan kompleks yang dapat mengabaikan indeks jika memutuskan pemindaian tabel lebih cepat, atau mungkin menggunakan semacam, atau mungkin mengatur halaman memori sesuka hatinya.
sumber
Saya baru saja menemukan pertanyaan ini melalui pertanyaan lain. Dengan asumsi bahwa pernyataan Anda bahwa hanya segelintir catatan yang mengasumsikan nilai 1 (dan itu adalah yang Anda minati), maka indeks yang difilter bisa menjadi pilihan yang baik. Sesuatu seperti:
Ini akan membuat indeks yang jauh lebih kecil sehingga pengoptimal cukup pintar untuk digunakan jika itu adalah predikat dalam kueri Anda.
sumber
yourBitColumn = @value
, maka pengoptimal tidak dapat menentukan apakah indeks yang difilter dapat digunakan.100 juta rekaman dengan hanya sedikit yang bidang bitnya disetel ke 1? Ya, menurut saya mengindeks bidang bit pasti akan mempercepat kueri bit = 1 catatan. Anda harus mendapatkan waktu pencarian logaritmik dari indeks dan kemudian hanya menyentuh beberapa halaman dengan catatan bit = 1. Jika tidak, Anda harus menyentuh semua halaman dari tabel catatan 100 juta.
Kemudian lagi, saya jelas bukan ahli database dan mungkin melewatkan sesuatu yang penting.
sumber
Jika distribusi Anda cukup dikenal dan tidak seimbang, seperti 99% baris adalah bit = 1 dan 1% adalah bit = 0, ketika Anda melakukan klausa WHERE dengan bit = 1, pemindaian tabel lengkap akan berlangsung sekitar waktu yang sama dengan pemindaian indeks. Jika Anda ingin mendapatkan kueri cepat di mana bit = 0, cara terbaik yang saya tahu adalah membuat indeks yang difilter, menambahkan klausa WHERE bit = 0. Dengan begitu, indeks tersebut hanya akan menyimpan baris 1%. Kemudian melakukan WHERE bit = 0 hanya akan membiarkan pengoptimal kueri memilih indeks itu, dan semua baris darinya akan menjadi bit = 0. Anda juga mendapat manfaat memiliki ruang disk yang sangat kecil yang diperlukan dibandingkan indeks penuh pada bit .
sumber
Meskipun saya tidak berpikir saya akan mengindeks kolom bit HANYA dengan sendirinya, sangat umum untuk memasukkan kolom bit sebagai bagian dari indeks gabungan.
Contoh sederhananya adalah indeks di ACTIVE, LASTNAME, bukan hanya nama belakang, saat aplikasi Anda hampir selalu mencari pelanggan aktif.
sumber
Jika Anda belum membacanya, Jason Massie menulis artikel baru-baru ini yang membahas topik ini.
http://statisticsio.com/Home/tabid/36/articleType/ArticleView/articleId/302/Never-Index-a-BIT.aspx
Sunting: Lokasi artikel baru - http://sqlserverpedia.com/blog/sql-server-bloggers/never-index-a-bit
Mesin wayback untuk lokasi artikel "Baru" sebelumnya: http://web.archive.org/web/20120201122503/http://sqlserverpedia.com/blog/sql-server-bloggers/never-index-a-bit/
Lokasi SQL Server Pedia baru adalah Toadworld, yang memiliki artikel baru dari Kenneth Fisher yang membahas topik ini:
http://www.toadworld.com/platforms/sql-server/b/weblog/archive/2014/02/17/dba-myths-an-index-on-a-bit-column-will-never-be- used.aspx
mesin wayback: http://web.archive.org/web/20150508115802/http://www.toadworld.com/platforms/sql-server/b/weblog/archive/2014/02/17/dba-myths-an -index-on-a-bit-column-will-never-be-used.aspx
sumber
Tentu saja itu berharga, terutama jika Anda perlu mengambil data dengan nilai itu. Ini akan mirip dengan menggunakan matriks renggang daripada menggunakan matriks normal.
Sekarang dengan SQL 2008 Anda dapat menggunakan fungsi partisi, dan Anda dapat memfilter data yang masuk ke dalam indeks. Kerugian untuk versi sebelumnya adalah bahwa indeks akan dibuat untuk semua data, tetapi ini dapat dioptimalkan dengan menyimpan nilai yang menarik dalam grup file terpisah.
sumber
Seperti yang dikatakan orang lain, Anda pasti ingin mengukur ini. Saya tidak ingat di mana saya membaca ini, tetapi kolom harus memiliki kardinalitas yang sangat tinggi (sekitar 95%) agar indeks menjadi efektif. Tes terbaik Anda untuk ini adalah membangun indeks dan memeriksa rencana eksekusi untuk nilai 0 dan 1 dari bidang BIT. Jika Anda melihat operasi pencarian indeks dalam rencana eksekusi, maka Anda tahu bahwa indeks Anda akan digunakan.
Tindakan terbaik Anda adalah menguji dengan tabel SELECT * FROM dasar WHERE BitField = 1; membuat kueri dan perlahan-lahan membangun fungsionalitas dari sana selangkah demi selangkah hingga Anda memiliki kueri yang realistis untuk aplikasi Anda, memeriksa rencana eksekusi dengan setiap langkah untuk memastikan bahwa pencarian indeks masih digunakan. Diakui, tidak ada jaminan bahwa rencana pelaksanaan ini akan digunakan dalam produksi, tetapi kemungkinan besar akan digunakan.
Beberapa informasi dapat ditemukan di forum sql-server-performance.com dan di artikel referensi
sumber
"Saya ingat pernah membaca di satu titik bahwa mengindeks bidang dengan kardinalitas rendah (jumlah nilai berbeda yang rendah) tidak benar-benar bermanfaat"
Itu karena SQL Server akan selalu merasa lebih efisien dengan hanya melakukan pemindaian tabel daripada membaca indeks. Jadi pada dasarnya indeks Anda tidak akan pernah digunakan dan itu sia-sia untuk memeliharanya. Seperti yang dikatakan orang lain, mungkin baik-baik saja dalam indeks gabungan.
sumber
Jika tujuan Anda adalah membuat kueri untuk rekaman di mana nilai bidang bit sama dengan '1' lebih cepat, Anda dapat mencoba tampilan terindeks dari tabel dasar Anda yang hanya berisi rekaman di mana bidang bit Anda sama dengan '1'. Dalam edisi perusahaan, jika kueri dapat menggunakan tampilan yang diindeks daripada tabel yang ditentukan untuk meningkatkan kinerja kueri, itu akan menggunakan tampilan. Secara teori, ini akan meningkatkan kecepatan kueri pemilihan yang hanya mencari rekaman dengan nilai bidang bit '1'.
http://www.microsoft.com/technet/prodtechnol/sql/2005/impprfiv.mspx
Semua ini mengasumsikan Anda adalah Microsoft SQL Server 2005 Enterprise. Hal yang sama mungkin berlaku untuk 2008, saya tidak terbiasa dengan versi itu.
sumber
Jika Anda ingin mengetahui apakah indeks memiliki efek yang Anda inginkan: uji dan uji lagi.
Secara umum Anda tidak menginginkan indeks yang tidak cukup mempersempit tabel Anda, karena biaya untuk mempertahankan indeks. (biaya> keuntungan). Tetapi jika indeks dalam kasus Anda akan memotong tabel menjadi dua, Anda mungkin mendapatkan sesuatu selain meletakkannya di atas meja. Itu semua tergantung pada ukuran / struktur tabel Anda dan bagaimana Anda menggunakannya (jumlah baca / tulis).
sumber
Dengan sendirinya, tidak karena menghasilkan selektivitas yang sangat sedikit. Sebagai bagian dari indeks majemuk. sangat mungkin tetapi hanya setelah kolom kesetaraan lainnya.
sumber
Anda tidak dapat mengindeks bidang bit di SQL Server 2000, seperti yang ditunjukkan di Buku Daring pada saat itu:
Ya, jika Anda hanya memiliki sedikit baris, dari jutaan, indeks akan membantu. Tetapi jika Anda ingin melakukannya dalam hal ini Anda perlu membuat kolom a
tinyint
.Catatan : Manajer Perusahaan tidak akan membiarkan Anda membuat indeks pada kolom bit. Jika mau, Anda masih dapat membuat indeks secara manual pada kolom bit:
Tetapi SQL Server 2000 tidak akan benar-benar menggunakan indeks seperti itu - menjalankan kueri di mana indeks akan menjadi kandidat yang sempurna, misalnya:
SQL Server 2000 akan melakukan pemindaian tabel, bertindak seolah-olah indeks tersebut bahkan tidak ada. Jika Anda mengubah kolom menjadi tinyint SQL Server 2000 akan melakukan pencarian indeks. Juga, kueri tidak tercakup berikut:
Ini akan melakukan pencarian indeks, diikuti oleh pencarian bookmark.
SQL Server 2005 memiliki dukungan terbatas untuk indeks pada kolom bit. Sebagai contoh:
akan menyebabkan pencarian indeks melalui indeks penutup. Tapi kasus yang tidak tertutup:
tidak akan menyebabkan pencarian indeks diikuti oleh pencarian bookmark, ia akan melakukan pemindaian tabel (atau pemindaian indeks berkerumun), daripada melakukan pencarian indeks yang diikuti dengan pencarian bookmark.
Diverifikasi dengan eksperimen dan observasi langsung.
sumber
jawaban yang sangat terlambat ...
Ya, ini dapat berguna menurut tim SQL CAT (diperbarui, telah dikonsolidasikan)
sumber
Apakah ini pertanyaan umum? Ini mungkin bermanfaat saat mencari "segelintir" rekaman tetapi tidak akan banyak membantu Anda di baris lain. Apakah ada cara lain untuk mengidentifikasi data?
sumber
Kardinalitas adalah satu faktor, yang lainnya adalah seberapa baik indeks membagi data Anda. Jika Anda memiliki sekitar setengah 1 dan setengah 0, maka itu akan membantu. (Dengan asumsi bahwa indeks adalah jalur yang lebih baik untuk dipilih daripada indeks lainnya). Namun, seberapa sering Anda memasukkan dan memperbarui? Menambahkan indeks untuk kinerja SELECT juga merusak kinerja INSERT, UPDATE dan DELETE, jadi ingatlah itu.
Saya akan mengatakan, jika 1 hingga 0 (atau sebaliknya) tidak lebih baik dari 75% hingga 25%, jangan repot-repot.
sumber
ukur waktu respons sebelum dan sesudah dan lihat apakah itu bermanfaat; secara teoritis itu harus meningkatkan kinerja untuk kueri yang menggunakan bidang yang diindeks tetapi itu sangat tergantung pada distribusi nilai benar / salah dan bidang lain yang terlibat dalam kueri yang Anda khawatirkan
sumber
Ian Boyd benar ketika dia mengatakan bahwa Anda tidak dapat melakukannya melalui Manajer Perusahaan untuk SQL 2000 (lihat catatannya tentang pembuatannya melalui T-SQL.
sumber
Anda harus pintar di sini untuk membuat kueri, Anda harus mengetahui nilai beban pada kolom Anda jika beban benar lebih banyak di sistem Anda dan Anda ingin memeriksa semua nilai yang benar tulis kueri Anda untuk memeriksa bukan salah .. itu akan banyak membantu , itu hanya tipuan.
sumber