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

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

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

它是否会“内联”计算列表达式,就好像我直接在查询中指定了大小写一样?

如果计算列的表达式在非模式绑定(bind)的用户定义函数中呢?

编辑

我的例子不是很好,因为如前所述,HasBalance 列不会有很好的数据分布。但是暂时忽略索引本身的效率,查询处理器在选择索引和选择执行计划时是否会基本上将上述查询视为如下所示?
SELECT ID, Name, Balance
FROM Customers
WHERE Balance > 0

最佳答案

这取决于数据的分布,现在你只有 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) ELSE (0) END,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)) 向前订购)

关于sql-server - Microsoft SQL Server 会有效地处理非持久化计算列吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3480039/

10-16 13:26