2013-06-21 97 views
0

我有以下表A:如何避免全表掃描多重可搜索列查詢?

id | col1 | col2 | col3 | ... | col66 
------------------------------------- 
999| 1 | 0 | 0 | ... | 1 

所有列COLX是searcheable和有其中66這意味着創建有效的索引是不可能的(至少我想是這樣)。

查詢可以看起來像:

SELECT id FROM tableA WHERE col21=1 AND col31=1 AND col64=1 

正如你看到的,我只需要與某些列被設置爲「1」檢索行。這組列可能會有所不同。你知道沒有全表掃描的任何方法都很費時嗎?我想我已經嘗試了一切,但沒有運氣:-(感謝

+0

這些查詢真的很慢,或者你不能同意mysql使用全面掃描嗎? – peterm

+0

@peterm他們實際上很慢。我不介意全表掃描,如果表只有5行:-)在我的情況下,大約需要0.4+秒來執行查詢,這是不可接受的。 –

回答

1

你可以像更改表的結構:

id type value 
999 col1 1 
999 col2 0 
--- 

而且,如果你認爲你可以添加人工PK需要它也關鍵的事情這裏是對的類型和價值綜合指數:INDEX (type,value)這樣你的查詢將使用該索引和搜索速度會更快

您的查詢將被轉換:

SELECT 
    id 
FROM 
    tableA 
WHERE 
    type IN ('col21','col31','col64') 
    AND value = 1 
+0

這是非常浪費的解決方案。原來的行浪費了70個字節。這將使用'(4 + 4 + 1)* 66' ='594'字節來存儲相同的信息,或幾乎10倍。 – mvp

+0

我同意,但類型可以標準化爲tinyint,這將節省空間,如果列的唯一值是1和0,您的位圖解決方案也是理想的選擇。 – Stephan

+0

@Stephan在這種情況下(如果BIT僅用於一列)爲它分配一個實際上等於TINYINT的字節。 –

2

爲了這樣的查詢:

SELECT id FROM tableA WHERE col21=1 AND col31=1 AND col64=1 

工作速度快,你必須創建複合索引,其中包括提到的所有領域:(col21, col31, col64)。我猜你不能預測需要的字段清單,所以它可能不適合你 - 除非你願意創建大量的索引。

更好的選擇是規範化你的表 - 創建一個將一個屬性存儲在一個單獨行中的從表。這將使得索引變得更容易,並且還可以保持任意數量的屬性。

UPDATE:還有一種可能性是用bitmaps替換0/1列。如果今天你有一個32位主鍵和66個微小的int列,行寬是4 + 66 = 70個字節。如果使用BIT數據類型(您需要2位列,MySQL中的最大BIT大小爲64位),則行寬變爲4+(66/8)= 13個字節,或者比以前減少近5倍。如果今天你的全部掃描時間是0.4秒,這個包裝將會是0.08秒,這對你來說可能是可以接受的。

+1

+1爲思維相似:) – Stephan

+0

添加了使用[BIT數據類型]的替代方法(http://dev.mysql.com/doc/refman/5.5/en/bit-type.html) – mvp

+0

我正在考慮使用BIT類型,但它有一個非常重要的缺點 - 很難搜索,即col40 = 1 AND col50 = 1。這是因爲我需要忽略其他列的值,這意味着我需要使用按位AND(&),它比當前解決方案快2倍,但仍然太慢。 –