2013-06-21 69 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倍,但仍然太慢。 –