对用于 BitWise 查询的 INT 列进行索引的最佳方法

GWR*_*GWR 6 index sql-server sql-server-2012 bitwise-comparison

基于 WHERE 子句中的按位比较对列进行索引以进行有效查找的最佳方法是什么,例如

SELECT ID, FLAGS, NAME FROM TABLE WHERE FLAGS & 4 = 4
Run Code Online (Sandbox Code Playgroud)

我的环境是SQL Server 2012。

据我了解,此类查询中不会使用 FLAGS 列上的索引。

我知道另一个选择是将 FLAGS 列分解为单独的列,但我想避免这种情况,因为在某些情况下,这意味着 25 个以上的新列,每个列都需要索引组合来支持常见查询。

有没有什么方法可以对单列建立索引以使按位查询更有效?

我尝试按照下面 dudu 的建议使用带有索引的计算列,但是当我在具有聚集索引的表上使用并开始选择列(而不是仅仅选择 count(*) 时,它不再使用该索引新的计算列。

SELECT 
* 
INTO 
    MYTABLE
FROM 
(
    SELECT 'A' COL_A, 'A' COL_B, CAST(129 AS INT) FLAGS UNION
    SELECT 'B' COL_A, 'D' COL_B, CAST(129 AS INT) FLAGS UNION
    SELECT 'C' COL_A, 'S' COL_B, CAST(129 AS INT) FLAGS UNION
    SELECT 'D' COL_A, 'F' COL_B, CAST(129 AS INT) FLAGS UNION
    SELECT 'E' COL_A, 'T' COL_B, CAST(128 AS INT) FLAGS UNION
    SELECT 'F' COL_A, 'D' COL_B, CAST(128 AS INT) FLAGS UNION
    SELECT 'G' COL_A, 'D' COL_B, CAST(128 AS INT) FLAGS UNION
    SELECT 'H' COL_A, 'X' COL_B, CAST(128 AS INT) FLAGS 
) SRC

CREATE CLUSTERED INDEX IX_CLU_A ON MYTABLE(COL_A)



ALTER TABLE MYTABLE ADD FLAG_BIT_1 AS (CAST ((FLAGS & 1) AS BIT))
CREATE INDEX MYTABLE_IX_FLAG_BIT_1 ON MYTABLE (FLAG_BIT_1)

SELECT * FROM MYTABLE WHERE FLAGS & 1 = 1
SELECT * FROM MYTABLE WHERE FLAG_BIT_1 = 1

SELECT COUNT(*) FROM MYTABLE WHERE FLAGS & 1 = 1
SELECT COUNT(*) FROM MYTABLE WHERE FLAG_BIT_1 = 1
Run Code Online (Sandbox Code Playgroud)

Dav*_*itz 3

计算(又名虚拟)列上的索引


演示

with t(i) as (select 0 union all select i+1 from t where i<999) 
select 1+t0.i+1000*t1.i as FLAGS into MyTable from t t0,t t1 option (maxrecursion 0)
Run Code Online (Sandbox Code Playgroud)
alter table MyTable add flag_bit_2 as (cast ((FLAGS & 4) as bit))
create index MyTable_ix_flag_bit_2 on MyTable (flag_bit_2)
Run Code Online (Sandbox Code Playgroud)
select count(*) from MyTable where flag_bit_2 = 1
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 这是人口统计数据的问题。如果大部分行符合条件,则使用索引是没有意义的。 (2认同)