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   

但它的范围要广得多,而且类别不仅仅是 Zone。用户将寻找与至少一个选定区域匹配的 sku。我打算查询这个(如果用户检查了“zone2,zone4,zone6”)

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 时才有用?

谢谢,罗伯

4

2 回答 2

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
于 2015-12-19T02:29:13.290 回答
0

索引布尔值几乎总是无用的。

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

让我们讨论如何使用一些大小的 INT 来实现,命名为zones

zone1 是最低位 (1<<0 = 1) zone2 是下一位 (1<<1 = 2) zone3 是下一位 (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 = 区域 6 | 区域4 | zone2 --|按位或运算符在哪里。

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

(zones & 42) = 42有效地检查所有 3 个位是否都“打开”。
(zones & 42) = 0有效地检查所有 3 个位是否“关闭”。
在这两种情况下,它都忽略了其他位。

42 可以表示为((1<<5) | (1<<3) | (1<<1)). 由于优先规则,我建议使用比您认为必要的更多的括号。

1 << 5表示“移位”15

于 2015-12-19T23:20:44.707 回答