我很难用这样的方式来表达这个问题,这样就不会出现持久的索引计算列的结果。
我的问题是,如果我有一张表如:
CREATE TABLE Customers (
ID int,
Name nvarchar(50),
Balance money,
HasBalance AS CONVERT(bit, CASE WHEN Balance > 0 THEN 1 ELSE 0 END)
)
假设有一个关于Balance的索引,SQL查询处理器是否会有效地处理查询,例如:
SELECT ID, Name, Balance
FROM Customers
WHERE HasBalance = 1
它是否基本上“内联”了计算列表达式,就像我直接在查询中指定了案例一样?
如果计算列的表达式是在非模式绑定的用户定义函数中呢?
修改
我的例子并不好,因为如上所述,HasBalance列不会有非常好的数据分布。但忽略索引本身的效率,查询处理器在选择索引和选择执行计划时,基本上会如下所示处理上述查询吗?
SELECT ID, Name, Balance
FROM Customers
WHERE Balance > 0
答案 0 :(得分:4)
这取决于数据的分布,现在你只有2个可能的值1和0 ....所以除非你有99%的数据是一个值,你的选择性将非常差,那么它必须扫描整个索引以找到所有正值或负值
编辑.....这是发生了什么,你得到一个表扫描
CREATE TABLE Customers (
ID int,
Name nvarchar(50),
Balance money,
HasBalance AS CONVERT(bit, CASE WHEN Balance > 0 THEN 1 ELSE 0 END)
)
insert Customers values(1,'d',100)
insert Customers values(2,'d',-2)
insert Customers values(3,'d',-4)
insert Customers values(4,'d',3)
insert Customers values(5,'d',5)
create index ix_test on Customers(Balance)
SELECT ID, Name, Balance
FROM Customers
WHERE HasBalance = 0
set showplan_text on
| - 表扫描(OBJECT:([master]。[dbo]。[Customers]), 在哪里:(CONVERT(位,当[主]] [dbo]。[客户]。[余额]>($ 0.0000) 那么(1)ELSE(0)END,0)= [@ 1]))
看看这个
SELECT Balance
FROM Customers
WHERE HasBalance = 0
- 索引扫描(OBJECT:([master]。[dbo]。[Customers]。[ix_test]),WHERE :( CONVERT(bit, 情况[主] [dbo]。[客户]。[余额]>($ 0.0000)然后(1)ELSE(0)END,0)= [@ 1]))
SELECT Balance
FROM Customers
WHERE Balance > 0
| - 索引搜寻(OBJECT:([master]。[dbo]。[Customers]。[ix_test]),SEEK:([master]。[dbo]。[Customers] 。[余额]> CONVERT_IMPLICIT(钱,[@ 1],0))有序前进)