Microsoft SQL Server是否可以有效地处理非持久计算列?

时间:2010-08-13 19:13:55

标签: sql-server indexing calculated-columns

我很难用这样的方式来表达这个问题,这样就不会出现持久的索引计算列的结果。

我的问题是,如果我有一张表如:

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

1 个答案:

答案 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))有序前进)