Sql-Server

帶有查找表說明的位遮罩標誌

  • July 22, 2014

我從外部來源收到了一個數據集,其中包含幾個位遮罩欄位作為 varchars。它們的長度低至 3,長至 21 個值。我需要能夠使用 AND 或 OR 邏輯基於這些欄位執行 SELECT 查詢。

使用計算欄位,我只是將位轉換為整數值,我可以通過使用簡單的 WHERE rowvalue = requestvalue 輕鬆找到與 AND 查詢匹配的行,但 OR 邏輯需要使用按位 & 來查找匹配記錄。

鑑於我需要處理其中的幾個列並從數億條記錄中進行選擇,我覺得在執行按位 & 操作來過濾我的 SELECT 結果時會產生巨大的性能損失。

我從搜尋中發現了這個答案,它看起來可能符合我的需求,但我需要澄清它是如何實現的。

這是否像創建一個包含所有可能搜尋條件的查找表一樣簡單?

使用 (a & b) 的 3 位範例(編輯:錯誤的按位運算)

001,001
001,011
001,101
001,111
010,010
010,011
010,110
011,011
011,111
etc

作者提到它最初是違反直覺的,但我不禁覺得我對解決方案的解釋不正確,因為這會給我一個可能有數十億行的查找表。

對我上面連結的答案或其他可以保留現有數據庫的建議的任何澄清表示讚賞。

編輯:一個使用小數據的更具體的例子。

四個標誌,HasHouse、HasCar、HasCat、HasDog,0000 是沒有,1111 是全部。

可以翻轉任意數量的標誌,從全部到無,並且必須過濾選擇匹配全部(使用精確值比較)或至少 1(使用按位 &)的結果。

為每個位遮罩添加一個計算列是可以的,但是為超過 100 位的每個位添加一個列,加上如何插入/更新數據是我試圖尋找替代解決方案的原因。

我部分同意 Aaron 的評論 - 在儲存 21 條不相關資訊的最一般情況下,您可能會使用 21 位列。作為一般解決方案,它很可能是您的最佳解決方案。如果您有多個位遮罩的 varchar 列,那將轉換為可能有一百多個位標誌的行。僅供參考,當您不將它們定義為 NULLable 時,21 位將儲存為 3 個字節,從而消除了 NULL 點陣圖中空間的必要性。由於您有多個位遮罩列,因此您最終將每 8 位混合成一個字節。

SQL Server 最終對您的多列查詢所做的最終是一堆位遮罩常式(是的!SQL Server 使用位遮罩,因此它們本身的概念不能全是壞的!)但對於普通案例,它使生活對你來說更容易。

如果我們有更多關於您執行的查詢類型的資訊,我們可能會提供更好的建議,因為最終案例決定了設計。

如果您堅持使用 COMPUTED 列,我會**堅持並索引它,**如果您還沒有的話。它有助於一些查詢,例如

  1. 完全匹配

WHERE computedInt = POWER(2, 6) – 位位置 7 2. 與第 15 位匹配和或匹配其他 2 位(第 10 位和第 7 位)

其中 computedInt >= Power(2,14) AND computedInt < Power(2,15) AND computedInt & (Power(2,9) + Power(2,6)) > 0

但這些可能是異國情調的樣本,但在某些情況下也是真實的。它肯定不會比 21 個單獨的位列差太多,是的,您的語句可能更容易編寫,但請記住 SQL Server 已將它們混合為 3 個字節儲存,並且無論如何都會進行位取消屏蔽!您會認為如果位遮罩都不好 (無一例外),那麼 SQL Server 就不會這樣做,對吧?

編輯

重新的場景

四個標誌,HasHouse、HasCar、HasCat、HasDog,0000 是沒有,1111 是全部。

一次測試所有 4 位並執行單個基於整數的操作會更有效且邏輯上更方便,例如

WHERE computedInt & (POWER(2,10)+POWER(2,5)+POWER(2,3)+POWER(2,1)) = 0 -- has none
WHERE computedInt & (POWER(2,10)+POWER(2,5)+POWER(2,3)+POWER(2,1)) &gt; 0 -- has one or more

假設這是您對錶最常用的查詢,您甚至可以將這四列分組到另一個計算列中並分別對其進行索引,從而不需要位遮罩(只需使用=0and測試結果 int &gt;0)。你甚至可以更進一步,只是預先計算答案……課程的馬。

引用自:https://dba.stackexchange.com/questions/39016