2009-09-21 78 views
4

是以下查詢有效的MySQL:(位)的超集和子集在MySQL

SELECT * FROM table WHERE field & number = number; 
# to find values with superset of number's bits 

SELECT * FROM table WHERE field | number = number; 
# to find values with subset of number's bits 

...如果該字段的索引已經建立?

如果沒有,有沒有辦法讓它運行得更快?

+2

這是一個很好的問題,但您需要接受一些答案 - 20%不會邀請人們嘗試回答您 – Fragsworth 2009-09-21 22:34:29

回答

6

更新:

參見性能細節在我的博客此項:


SELECT * FROM table WHERE field & number = number 

SELECT * FROM table WHERE field | number = number 

該指數可以用兩種方法是有效的:

  1. 爲了避免早期表掃描(因爲比較值包含在索引本身)
    • 爲了限制檢查的值的範圍。上述

無論條件在查詢是可優化搜索,這是該指數將不會被用於範圍掃描(與條件,因爲它們是現在)。

但是,點1仍然成立,並且該索引可能有用。

如果您的表中包含每行平均有100個字節和1,000,000記錄,則表掃描將需要掃描100 Mb數據。

如果你有一個索引(用4字節鍵,6字節行指針和一些內部開銷),查詢需要如果濾波器成功僅僅10 Mb數據和其它的數據從表掃描。

  • 如果您的條件不具有選擇性(您有很高的可能性以匹配條件),表掃描更有效。
  • 如果您的情況有選擇性(您的概率很低以符合條件),索引掃描更有效。

這兩個查詢都需要掃描整個索引。

但通過重寫AND查詢,您也可以從索引範圍中受益。

這種情況:

field & number = number

如果number集的最高位在field設置得只能匹配的字段。

,並且應該只提供這種額外的條件查詢:

SELECT * 
FROM table 
WHERE field & number = number 
     AND field >= 0xFFFFFFFF & ~((2 << FLOOR(LOG(2, 0xFFFFFFFF & ~number))) - 1) 

這將使用範圍用於粗過濾和精過濾的條件。

number的位數越多,結尾越好。

+0

還有OR優化的可能性:如果字段的位數高於數字的最高位,那麼「field | number = number」永遠不會成立。所以:SELECT * FROM table WHERE field | number = number AND字段<2 << FLOOR(LOG(2,number));我還可以想象使用多個字段的最高位來進一步優化構建具有多個範圍的查詢。極端的情況是當明確指定了字段的每個值時(使用「字段IN(值1,...)」)。無論如何,這是一個很好的答案。 – Meisner 2009-09-29 22:17:31

1

我懷疑優化器會想出一個......

也許你可以調用EXPLAIN這些查詢並確認我的悲觀猜測。 (當然,大部分查詢計劃決策都是基於給定數據庫的具體實例,即可變數據量和/或僅具有不同統計概況的數據可能產生不同的計劃)。

假設表中有大量的行,並且「bitwised」標準保持足夠的選擇性),通過用IN構造重寫查詢來避免每一行上的按位操作,可以實現可能的優化或具有JOIN)

類似的東西(概念,即,未測試)

CREATE TEMPORARY TABLE tblFieldValues 
    (Field INT); 

INSERT INTO tblFieldValues 
    SELECT DISTINCT Field 
    FROM table; 

-- SELECT * FROM table WHERE field | number = number; 
-- now becomes 
SELECT * 
FROM table t 
WHERE field IN 
    (SELECT Field 
    FROM tblFieldValues 
    WHERE field | number = number); 

這樣需要的方法的全部好處與不同的用例(所有這些具有相當大的數目來評價因爲否則直接的「WHERE field number = number」方法是有效的足夠),但我懷疑這可能會更快。如果不需要每次重新創建「tblFieldValues」,則可以獲得進一步的收益。這個表的有效創建當然意味着原始表中的字段索引。

+0

這是一個解決方案,通過減少字段值的計數可以獲得越來越多的樂趣。爲了這種優化,我會考慮將BIGINT字段分成TINYINT字段集。 – Meisner 2009-09-29 22:08:12

0

我已經嘗試過這個,並且按位操作不足以阻止Mysql在「字段」列上使用索引。但是,很可能對索引進行全面掃描。