Saya ingin memiliki pencarian cepat berdasarkan jika dua kolom sama. Saya mencoba menggunakan kolom yang dihitung dengan indeks, tetapi SQL Server tampaknya tidak menggunakannya. Jika saya hanya menggunakan kolom bit yang dihuni secara statis dengan indeks, saya mendapatkan pencarian indeks yang diharapkan.
Tampaknya ada beberapa pertanyaan lain seperti ini di luar sana, tetapi tidak ada yang berfokus pada mengapa indeks tidak akan digunakan.
Meja Uji:
CREATE TABLE dbo.Diffs
(
Id int NOT NULL IDENTITY (1, 1),
DataA int NULL,
DataB int NULL,
DiffPersisted AS isnull(convert(bit, case when [DataA] is null and [DataB] is not null then 1 when [DataA] <> [DataB] then 1 else 0 end), 0) PERSISTED ,
DiffComp AS isnull(convert(bit, case when [DataA] is null and [DataB] is not null then 1 when [DataA] <> [DataB] then 1 else 0 end), 0),
DiffStatic bit not null,
Primary Key (Id)
)
create index ix_DiffPersisted on Diffs (DiffPersisted)
create index ix_DiffComp on Diffs (DiffComp)
create index ix_DiffStatic on Diffs (DiffStatic)
Dan Pertanyaannya:
select Id from Diffs where DiffPersisted = 1
select Id from Diffs where DiffComp = 1
select Id from Diffs where DiffStatic = 1
sumber
COALESCE
pada titik ini; Saya percayaCASE
pernyataan sudah dijamin untuk kembali0
atau1
, tetapiISNULL
hanya hadir sehingga SQL Server akan menghasilkan non-nullableBIT
untuk kolom yang dihitung. Namun,COALESCE
masih akan menghasilkan kolom yang dapat dibatalkan. Jadi satu dampak dari perubahan ini, dengan atau tanpaCOALESCE
, adalah bahwa kolom yang dikomputasi sekarang dapat dibatalkan tetapi pencarian indeks dapat digunakan.COALESCE
? Mengapa saya menyimpannya?COALESCE
. Saya mencoba mempertahankan tampilan dan maksud kode asli Anda, dan tidak menguji tanpa itu, sehingga pengujian akan ada pada Anda. (Saya tidak bisa menjelaskan mengapa Anda harusISNULL
ada di tempat pertama, baik.)Ini adalah batasan spesifik dari logika pencocokan kolom SQL Server yang dikomputasi, saat terluar
ISNULL
digunakan, dan tipe data kolom tersebutbit
.Laporan bug
Untuk menghindari masalah ini, salah satu dari solusi berikut dapat digunakan:
ISNULL
(satu-satunya cara untuk membuat kolom yang dihitungNOT NULL
).bit
tipe data sebagai tipe terakhir dari kolom yang dihitung.PERSISTED
dan aktifkan tanda jejak 174 .Detail
Inti dari masalah ini adalah bahwa tanpa jejak bendera 174, semua referensi kolom yang dihitung dalam kueri (bahkan bertahan) selalu diperluas ke definisi dasar sangat awal dalam kompilasi permintaan.
Gagasan ekspansi adalah bahwa hal itu dapat memungkinkan penyederhanaan dan penulisan ulang yang hanya dapat bekerja pada definisi, bukan pada nama kolom saja. Misalnya, mungkin ada predikat dalam kueri yang merujuk pada kolom yang dihitung yang dapat membuat bagian dari perhitungan menjadi berlebihan, atau lebih dibatasi.
Setelah penyederhanaan dan penulisan ulang awal dipertimbangkan, kompilasi permintaan mencoba untuk mencocokkan ekspresi dalam permintaan dengan kolom yang dihitung (semua kolom yang dihitung, tidak hanya yang awalnya ditemukan dalam teks permintaan).
Ekspresi kolom yang dihitung tidak berubah cocok dengan kolom yang dihitung sebelumnya tanpa masalah dalam kebanyakan kasus. Tampaknya ada bug ketika khusus untuk mencocokkan ekspresi
bit
tipe, dengan terluarISNULL
. Pencocokan tidak berhasil dalam kasus khusus ini, bahkan di mana pemeriksaan terperinci dari internal menunjukkan bahwa itu harus berhasil.sumber