2015-12-19 29 views
1

我的问题是在您的客户使用大量小字段时构建索引。如何索引宽泛的布尔表

考虑搜索的以下几点: (不能改变它,这就是客户端提供)

SKU zone1 zone2 zone3 zone4 zone5 zone6 zone7 zone8 zone9 zone10 zone11 
A123    1  1  1  1  1  1  1  1 
B234    1  1  1  1  1  1  1  
C345      1  1  1  1  1  1 

但它是非常广泛的,而且有很多种类较多不仅仅是区。 用户将寻找与至少一个选定区域相匹配的skus。我打算用(如果用户选中“2区,zone4中,区段6”)来查询这个

select SKU from TABLE1 where (1 IN (zone2,zone4,zone6)) 

有什么优势,索引与多层次的指数,像这样:

create index zones on table1 (zone1,zone2,zone3,zone4,zone5,zone6,zone7,zone8,zone9,zone10,zone11) 

还是会说只有当用户检查zone1时才有用?

感谢, 罗布

+1

布尔型字段上的索引是浪费时间,因为每行只有两个可能的值。另外,如果您按列的精确顺序搜索列内容,这意味着搜索必须先在zone1上,然后再添加zone2,然后添加zone3;否则,您的*多层索引*将仅工作。如果您在zone5中搜索内容而没有1,2,3和4(以此顺序),那么索引将毫无用处。 –

+0

同意@KenWhite。唯一真正的优化方法是重新设计它。也许你可以添加另一个设计得更好的表,并使用一个触发器来保持它与此表同步。 – Barmar

+0

很遗憾,你不能重新设计它,因为用一个更加规范化的表格,你有一个'sku'和'zones'的列,在那里你可以有多行sku(一个用于每个区域),然后这将允许一个有用的指数。对于宽行来说,除了定位SKU之外,索引不会有任何好处;其余的根本无法进行优化。 –

回答

1

你应该结构中的数据为:

create table SKuZones (
    Sku int not null, 
    zone varchar(255) 
) 

这将与将SKU有1.地方进行填充,然后这可能需要对指数的巨大优势SKUZones(zone)索引。一个查询如:

select SKU 
from SKUZones 
where zone in ('zone2', 'zone4', 'zone6'); 

将很容易利用索引。但是,如果数据的结构不适合关系数据库,则查询效率会更难。如果你可以添加到表中的列,你可以采取

一种方法如下:

  • 添加一个名为zones或类似的东西新列。
  • 使用触发器填充列中每个“1”的值(因此数据中第一行的“zone3 zone4 zone5 ...”)。
  • 在列上构建全文索引。
  • 使用match against
0

索引布尔值几乎总是没用运行查询。

如果使用SET数据类型该怎么办?或者BIGINT UNSIGNED

讲起过如何与一些大小INT做到这一点,一个名为zones

ZONE1是底位(1 < < 0 = 1) ZONE2是下位(1 < < 1 = 2) 3区是下一个位(1 < < 2 = 4) zone4中是下一个位(1 < < 3 = 8) 等

where (1 IN (zone2,zone4,zone6))变得 where (zones & 42) != 0

检查设置的所有3个区域:where (zones & 42) = 42

至于索引,没有索引可以帮助这个设计;仍然会有一个表扫描。

如果有11个区域,那么SMALLINT UNSIGNED(2个字节)就足够了。这将比其他设计更紧凑,因此可能更快。

对于这个查询,你可以有一个 “覆盖” 的索引,这有助于一些: select SKU from TABLE1 where (zones & 42) != 0 .. INDEX(zones, SKU)

(编辑)

42 = 32 | 8 | 2 = zone6 | zone4 | zone2 - 其中|是按位或运算符。

&是按位AND运算符。请参阅http://dev.mysql.com/doc/refman/5.6/en/non-typed-operators.html

(zones & 42) = 42有效检查所有这3个位是否都“打开”。
(zones & 42) = 0有效地检查所有这3位是否“关闭”。
在这两种情况下,它都忽略了其他位。可以表示为((1<<5) | (1<<3) | (1<<1))。由于优先规则,我建议使用比您认为必要的括号更多的括号。

1 << 5意味着“移位”1通过5位。

+0

是的,SET是我的原创设计,我认为它会很好地工作。 请您详细说明条件: where(zones&42)= 42;由于&字符不是运算符,我不确定这个条件是干什么的。 这是如何工作的? –

+0

看看我的编辑是否提供了足够的细节。 –