Jenis data untuk menyimpan array flag (bitmap / bit array)

15

Saya perlu menyimpan bit array untuk setiap record tabel, mendukung operasi berikut:

  • Menguji jika bit diatur, dan mengatur bit (menggunakan SQL)

  • Menanyakan dan mengatur nilai menggunakan ADO 2.8 (bukan ADO.NET)

  • Pengindeksan (untuk mendapat manfaat dari fitur "indeks penutup")

Jumlah bit maksimum yang akan disimpan dalam array ini adalah tetap, tetapi dapat melebihi 32 . Yaitu, kolom int sederhana tidak selalu berfungsi.

Dari apa yang saya lihat sejauh ini, opsi saya adalah:

  1. Gunakan beberapa kolom int
  2. Gunakan bigint (berfungsi selama jumlah bit <= 64)
  3. Gunakan biner
  4. ?

Opsi pertama akan berfungsi, tetapi membutuhkan sedikit refactoring dalam kode yang mengakses data. Pilihan kedua adalah bantuan sementara saja, dan dari pencarian saya sejauh ini saya tidak terlalu yakin apakah ADO bekerja dengan baik dengan bigint . Saya tidak punya pengalaman dengan biner , dan saya tidak mengetahui adanya opsi lain.

Jenis data apa yang akan Anda pilih, mengingat persyaratannya?

krlmlr
sumber

Jawaban:

12

Saya tidak bisa menganjurkan cukup kuat untuk tidak menggunakan satu bidang untuk ini.

Saat ini saya sedang berurusan dengan memelihara dataset yang sangat besar dengan bigintbidang bitmask dan itu sedikit mimpi buruk kinerja.

Jika Anda memeriksa sedikit pun baik-baik saja. Jika Anda memeriksa lebih dari satu bit, kinerja akan menurun dengan sangat cepat.

Karena sifat integer bitmask, distribusi data akan sangat tidak seimbang dan Anda akan mendapatkan rencana yang kurang optimal.

Beberapa pemeriksaan bit menghasilkan kisaran atau pemindaian indeks dengan fungsi berjalan terhadap setiap baris. Ini berantakan.

Solusi saya sederhana - saya membuat meja untuk menyimpan PK untuk setiap kondisi yang akan diperiksa. Ini awalnya kontra-intuitif tetapi ruang yang dibutuhkan rendah (Anda hanya menyimpan PK) dan pencarian kilat cepat, terutama jika Anda menggunakan a UNIQUE CLUSTERED INDEX.

Anda dapat menambahkan kondisi sebanyak yang Anda inginkan tanpa mempengaruhi tabel utama Anda, dan pembaruan juga tidak mempengaruhi tabel utama Anda.

Pengindeksan sederhana karena Anda hanya mengindeks semua tabel pencarian secara individual, dan karena kunci berkerumun Anda sama pada tabel utama Anda dan pencarian semua evaluasi Anda adalah merge joinyang sangat efisien.

JNK
sumber
1
Bisakah Anda menguraikan sedikit lebih banyak tentang solusi Anda? Saya menemukan ini karena saya mencoba untuk mengatasi masalah dasar yang sama, tetapi tidak yakin bagaimana cara terbaik untuk melakukannya.
Joshua Frank
4

Jika yang perlu Anda simpan adalah jumlah benar / salah dalam jumlah moderat, Anda bisa menggunakan bittipe data.

Secara internal, SQL Server menyimpan bitkolom yang dikemas dalam byte "chunks." Jadi untuk hingga 8 bitkolom di tabel Anda, SQL menyimpannya sebagai 1 byte yang dikemas; 9-16 bitkolom dalam 2 byte, dan seterusnya.

Tidak terdengar seperti Anda akan mendekati batas kolom, jadi ini sepertinya cukup mudah. Dan tentu saja, menjaga mereka dipisahkan dengan baik seperti itu memungkinkan Anda untuk memberi nama kolom untuk keterbacaan dan mendapatkan semua kemungkinan pengindeksan seperti biasanya (jika bendera sangat selektif, indeks yang difilter mungkin berguna jika Anda dapat menargetkan 2008+).

Melakukan pengepakan bit sendiri akan membuatnya jauh lebih berbelit-belit untuk melakukan pengindeksan (mungkin bitkolom yang dihitung dan diindeks untuk mewakili setiap posisi topeng ... tapi kemudian Anda lebih buruk daripada menggunakan bitsecara langsung).

Jon Seigel
sumber