2009-12-16 76 views
2

快速的問題對DBA的在那裏:SQL索引 - 計算列VS場的計算列使用

說我有我的表2列,請將isDeleted(位)和DeletedDate(日期時間)。該表包含大約10,000,000行。

IsDeleted是一個計算列,用於檢查DeletedDate是否爲NULL;如果不是則返回1,如果是則返回0。

查詢此表將主要在IsDeleted列上完成。

有人可以給我一些建議,我應該在哪裏應用我的索引?

將它應用到IsDeleted字段帶來了由於SET引用標識符關閉引起的一系列問題,這不一定是交易斷路器,但會導致一些額外的工作。

即使我沒有直接查詢該字段,我是否會看到將它應用於DeletedDate的好處?我是否應該咬住子彈並將其添加到IsDeleted?兩者之間的性能差異可以忽略不計?

再次感謝;如果你想要澄清,給我留言,我會更新我的帖子。

回答

3

將索引放在位列上是沒有意義的,因爲它沒有足夠的選擇性。執行查詢時,SQL Server將確定要使用的最合適的索引。如果您的索引不夠有選擇性,它將被忽略,或者它可能決定執行索引掃描而不是索引查找。無論哪種方式,它不會真的幫助那麼多。

將索引放在DeletedDate上可能會對某些查詢有所幫助,但是由於選擇性的原因,對NULL和「任何值」進行過濾可能沒有那麼大的幫助。

我建議你閱讀本: Seek Vs. Scan

0

我不會想象你會看到將它添加到DeletedDate的任何好處。但是,如果您不確定,則應該很容易以兩種方式來測試性能。

1

上,其值被限定在一個很小的領域(顯然二值可能是最小的)沒有任何意義,除了特殊的邊緣屬性放置一個索引的情況下(例如當這兩行之間的行分佈爲90%-10%時)

這是因爲任何使用索引來查找其中一個值(假設行均勻分佈大約50-50)將返回表中總行數的大約一半。如果您要創建的平衡樹(B-Tree)索引深度爲三或四級,則意味着每行檢索到3或4個IO操作,這將超過表中的行數。

1

如果計算基於當前日期時間,則無法在IsDeleted 上放置索引,因爲計算列的結果是非確定性的。它是基於時間的,並且在每次調用時可能會有不同的結果。有關詳細信息,請參閱本msdn article

例如,如果表中有整數 列a和b,計算列 A + B可以被索引,但計算 列+ DATEPART(DD,GETDATE() ) 無法編制索引,因爲值 可能會在後續調用中更改。

如果日期比較變得過於昂貴,你必須安排一個更新語句運行每「X」時間設置值,請將isDeleted爲「已過期」日期:

UPDATE MyTable SET IsDeleted=1 WHERE IsDeleted=0 AND DeletedDate < getutcdate() 

編輯:最初我誤解了這個問題,當計算爲NULL與非NULL時,它將是確定性的。有了確定性的結果,PERSISTED關鍵字可用於存儲空檢查結果:

IsDeleted AS DeletedDate IS NOT NULL PERSISTED 

這避免了運行的datetime null檢查所有的時間。它將結果存儲在表中,直到您更新DeletedDate列。你需要測試這實際上是否有回報,但我不認爲DeletedDate NULL檢查將會非常昂貴。

索引這兩個屬性可能沒有多大意義,因爲您基本上想要分開2組:刪除和未刪除。

+0

這是真的嗎?檢查字段是否爲空看起來似乎不是邏輯上不確定的。 – 2009-12-16 21:38:54

+0

哦,我誤解了,我以爲你將DeletedDate與當前日期進行比較,然後編輯,或拉出答案並重新回答 – 2009-12-16 21:40:52

1

說的分佈是: 98請將isDeleted%= 0 2%=請將isDeleted 1

將SQL Server的足夠聰明的僅存儲在索引請將isDeleted記錄的信息?