4

我很难以一种不会为持久化、索引计算列显示结果的方式来表达这个问题。

我的问题是,如果我有一张桌子,例如:

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
4

1 回答 1

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]), WHERE:(CONVERT(bit,CASE WHEN [master].[dbo].[Customers].[Balance]>($0.0000)那么 (1) 否则 (0) 结束,0)=[@1]))

看看这个

SELECT Balance
FROM Customers
WHERE HasBalance = 0

--索引扫描(OBJECT:([master].[dbo].[Customers].[ix_test]), WHERE:(CONVERT(bit, CASE WHEN [master].[dbo].[Customers].[Balance]> ($0.0000) THEN (1) ELSE (0) END,0)=[@1]))

SELECT Balance
FROM Customers
WHERE Balance > 0

|--索引搜索(OBJECT:([master].[dbo].[Customers].[ix_test]), SEEK:([master].[dbo].[Customers].[Balance] > CONVERT_IMPLICIT(money,[ @1],0)) 已订购)

于 2010-08-13T19:18:38.090 回答