SQL Server中多个位字段的索引

Dan*_*l B 7 sql sql-server indexing sql-server-2008

我们目前有一个场景,其中一个表实际上有几个(10到15)布尔标志(不是可空bit字段).不幸的是,在逻辑层面上实际上不太可能简化这一点,因为布尔值的任何组合都是允许的.

有问题的表是一个事务表,最终可能有数千万行,插入和选择性能都非常关键.虽然我们目前还不太确定数据的分布,但是所有标志的组合应该提供相对良好的基数,即使其成为SQL Server使用的"有价值"索引.

典型的选择查询场景可能是仅基于3或4个标志来选择记录,例如WHERE FLAG3=1 AND FLAG7=0 AND FLAG9=1.为这些选择查询使用的所有标志组合创建单独的索引是不切实际的,因为它们中有很多.

鉴于这种情况,有效索引这些领域的建议方法是什么?该表是新的,因此现在还没有现有的数据需要担心,我们在表的实际实现中有相当大的灵活性.

目前我们正在考虑两个主要选项:

  • 创建一个包含所有位字段的索引(这可能包括int总是使用的1或2个其他字段).我担心的是,鉴于仅包含一些字段的典型用法,此方法将跳过索引并采用表扫描.让我们称之为选项A(阅读了一些回复后,似乎这种方法效果不好,因为索引中字段的顺序会有所不同,因此无法在所有字段上有效地索引).
  • 有效地执行我认为SQL Server在内部执行的操作,并使用二元运算符将位字段编码为单个int字段(AND-ing和OR-ing一起使用:1,2,4,8等).我在这里担心的是我们需要进行某种计算来查询这个编码字段,这会再次跳过索引.此解决方案的维护和复杂性也是一个问题.让我们把这个选项B. 附加信息:该参数用于这种方法,我们可以有一个相对简单和短期指标,其中包括从表和本场的一个或两个字段.其他字段将缩小需要评估的记录数量,并且由于编码字段将包含所有位字段,因此SQL Server将能够使用从索引中直接检索的数据执行计算(即索引扫描) )而不是表(即表扫描).

目前,我们明显倾向于选择B.为了完整起见,这将在SQL Server 2008上运行.

任何建议将不胜感激.

编辑:拼写,清晰度,查询示例,选项B的其他信息.

mar*_*c_s 6

单个BIT列通常不具有足够的选择性,甚至不能考虑在索引中使用.因此,单个BIT列上的索引确实没有意义 - 平均而言,您总是必须搜索表中大约一半的条目(50%选择性),因此SQL Server查询优化器将改为使用表扫描.

如果您在所有15 bit列上创建单个索引,那么您没有这个问题 - 因为您有15个是/否选项,您的索引将变得非常有选择性.

麻烦的是:位列的顺序很重要.只有在SQL语句使用最左侧BIT列中至少1-n的情况下才会考虑您的索引.

所以,如果您的索引已开启

Col1,Col2,Col3,....,Col14,Col15
Run Code Online (Sandbox Code Playgroud)

然后它可能用于使用的查询

  • Col1
  • Col1Col2
  • Col1Col2Col3 ....

等等.但它不能用于指定Col6,Col9和的查询Col14.

因此,我并不认为您的BIT列集合上的索引真的很有意义.

这15 BIT列是您用于查询的唯一列吗?如果没有,我会尝试将您最常用的BIT列与其他列组合在一起,例如索引Name和/ Col7或某些东西(然后您的BIT列可以为另一个索引添加一些额外的选择性)


Nei*_*ick 3

虽然可能有一些方法可以解决现有表模式的索引问题,但我会将其简化为规范化问题:

例如,我强烈建议创建一系列新表:

  1. 该位标志名称的查找表。例如CREATE TABLE Flags (id int IDENTITY(1,1), Name varchar(256))(如果您想手动控制 id,则不必将 id 设置为身份种子列 - 例如 2,4,8,16,32,64,128 作为二进制标志。)
  2. 创建一个新的链接表,其中包含原始数据表和新链接表的id,例如CREATE TABLE DataFlags_Link (id int IDENTITY(1,1), MyFlagId int, DataId int)

然后,您可以在表上创建索引DataFlags_Link并编写如下查询:

SELECT Data.*
FROM Data
INNER JOIN DataFlags_Link ON Data.id = DataFlags_Link.DataId
WHERE DataFlags_Link.MyFlagId IN (4,7,2,8)
Run Code Online (Sandbox Code Playgroud)

至于性能,这就是良好的 DBA 维护的用武之地。您需要适当地设置表上的 INDEX 填充因子和填充,并定期运行索引碎片整理或按计划重建索引。

性能和维护与数据库密切相关。两者缺一不可。