假设有一个包含两个字段"id"
和"value"
的表格。我创建了一个non-clustured index on "value"
字段有一个参数"@valueToCompare"
。
For example :
MyTable
Id(Int) Value(int)
1 9
2 11
3 13
4 7
5 8
6 20
@valueToCompare = 27
现在我想编写一个查询,它将给出满足"value & @valueToCompare = value"
条件的结果集
因此我的查询将是
select * from MyTable where value & @valueToCompare = value
将在计算后给出结果
9 & 27 =9
11 & 27 =11
13 & 27 =9
7 & 27 =3
8 & 27 =8
20 & 27 =16
现在这个查询的问题是优化器会执行index scan rather than Index seek
,因此效率会降低。
所以想知道有没有办法编写查询来实现索引查找。
注意:我将使用c#code
中的结果集答案 0 :(得分:0)
SQL Server不会使用索引来执行按位操作。你运气不好,但是你可以先通过CTE或派生表创建一个较小的结果集,然后在较小的集合上执行操作。
答案 1 :(得分:0)
由于@valueToCompare
的当前值参与其中一列的表达式,因此无法将其转换为索引搜索。但是,如果您愿意将各个标志拆分为各自的列,则可能会获得更快的查找速度。
要将int
从0表示为int.MaxValue
,您需要31位列 - 比如v0
到v30
,包含。您可以对它们建立索引,然后将搜索号拆分为单个位,然后运行查询。您可以编写与value & @valueToCompare = value
的二进制值对应的检查组合而不是@valueToCompare
。
例如,如果@valueToCompare
为9 10 或1001 2 ,则查询将如下所示:
SELECT ...
WHERE v0=1 AND v3=1
v0
是包含零位的列; v3
是包含第三位的列。这些是以二进制表示形式设置的两个位。
您可以让SQL Server为您管理这些列,而不是手动管理列。
create table bitfields (
id int,
value int,
v0 as value & 1 persisted,
v1 as value & 2 persisted,
v2 as value & 4 persisted,
v3 as value & 8 persisted,
v4 as value & 16 persisted,
v5 as value & 32 persisted,
v6 as value & 64 persisted,
v7 as value & 128 persisted
-- ...and so on
)
create index bitfields_idx on bitfields (v0,v1,v2,v3,v4,v5,v6,v7)
现在,您可以根据已经分离出的咬合值进行搜索。此表中value & 9 = 9
的查询如下所示:
SELECT ...
WHERE v0=1 AND v3=8
您比较vN
的值是2 N ,因此对于v0
它是1
,对于v1
它是2
},v2
为4
,v3
为8
,依此类推。
答案 2 :(得分:0)
索引搜索可能会或可能不会比扫描更有效。除了最高选择性查询之外,扫描窄覆盖索引可能比搜索和查找更快。
单个位列只能是0或1;它的选择性平均为50%,因此可能不是一个非常好的索引候选者。您可以创建索引,但考虑到查询的成本非常高,优化程序可能会也可能不会使用它。
将它组合到一个位域可能是更好的解决方案,如果你知道你的数据并巧妙地对这些位进行排序,从更高的选择性到更低的顺序,可能会更好。为了说明这个想法:
select * from MyTable where value < @valueToCompare and value & @valueToCompare = value