以下面的例子为例:
SELECT <CalculationA> As ColA,
<CalculationB> As ColB,
<CalculationA> + <CalculationB> As ColC
FROM TableA
Run Code Online (Sandbox Code Playgroud)
CalculationA 和CalculationB 会分别计算两次吗?
或者优化器是否足够聪明来计算一次并使用结果两次?
我想进行测试以查看自己的结果,但是,我不确定如何检查这样的事情。
我的假设是它会执行两次计算。
在哪种情况下,根据所涉及的计算,使用派生表或嵌套视图会更好吗?考虑以下:
SELECT TableB.ColA,
TableB.ColB,
TableB.ColA + TableB.ColB AS ColC,
FROM(
SELECT <CalculationA> As ColA,
<CalculationB> As ColB
FROM TableA
) As TableB
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我希望计算只执行一次?
请问有人可以证实或反驳我的假设吗?或者指导我如何为自己测试这样的东西?
谢谢。
计算列的值何时确定?
我猜这是一个新手问题,因为我在搜索中没有找到任何东西。
我在一个表上有一个持久计算列,它只是由连接列组成,例如
CREATE TABLE dbo.T
(
ID INT IDENTITY(1, 1) NOT NULL CONSTRAINT PK_T_ID PRIMARY KEY,
A VARCHAR(20) NOT NULL,
B VARCHAR(20) NOT NULL,
C VARCHAR(20) NOT NULL,
D DATE NULL,
E VARCHAR(20) NULL,
Comp AS A + '-' + B + '-' + C PERSISTED NOT NULL
);
Run Code Online (Sandbox Code Playgroud)
这Comp不是唯一的,并且 D 是每个组合的有效起始日期A, B, C,因此我使用以下查询来获取每个组合的结束日期A, B, C(基本上是 Comp 相同值的下一个开始日期):
SELECT t1.ID,
t1.Comp,
t1.D,
D2 = ( SELECT TOP 1 t2.D
FROM dbo.T t2
WHERE t2.Comp = …Run Code Online (Sandbox Code Playgroud) sql-server-2008 sql-server execution-plan computed-column bookmark-lookup
在我之前的一个问题中,在向表中添加新的计算列时禁用锁升级是个好主意吗?,我正在创建一个计算列:
ALTER TABLE dbo.tblBGiftVoucherItem
ADD isUsGift AS CAST
(
ISNULL(
CASE WHEN sintMarketID = 2
AND strType = 'CARD'
AND strTier1 LIKE 'GG%'
THEN 1
ELSE 0
END
, 0)
AS BIT
) PERSISTED;
Run Code Online (Sandbox Code Playgroud)
计算列是PERSISTED,并且根据计算列定义(Transact-SQL):
坚持
指定数据库引擎将计算值物理存储在表中,并在计算列所依赖的任何其他列更新时更新值。将计算列标记为 PERSISTED 允许在确定性但不精确的计算列上创建索引。有关更多信息,请参阅计算列上的索引。任何用作分区表的分区列的计算列都必须显式标记为 PERSISTED。当指定 PERSISTED 时,computed_column_expression 必须是确定性的。
但是当我尝试在我的列上创建索引时,我收到以下错误:
CREATE INDEX FIX_tblBGiftVoucherItem_incl
ON dbo.tblBGiftVoucherItem (strItemNo)
INCLUDE (strTier3)
WHERE isUsGift = 1;
Run Code Online (Sandbox Code Playgroud)
无法在表 'dbo.tblBGiftVoucherItem' 上创建过滤索引 'FIX_tblBGiftVoucherItem_incl',因为过滤器表达式中的列 'isUsGift' 是计算列。重写过滤器表达式,使其不包含此列。
如何在计算列上创建过滤索引?
或者
有替代的解决方案吗?
index sql-server filtered-index sql-server-2014 computed-column
我有一张桌子:
CREATE TABLE [dbo].[Realty](
[Id] [int] IDENTITY(1,1) NOT NULL,
[RankingBonus] [int] NOT NULL,
[Ranking] AS ([Id]+[RankingBonus]) PERSISTED NOT NULL
....
)
Run Code Online (Sandbox Code Playgroud)
还有一个观点:
CREATE View [dbo].[FilteredRealty] AS
SELECT
realty.Id as realtyId,
...
COALESCE(realty.Wgs84X, ruian_cobce.Wgs84X, ruian_obec.Wgs84X) as Wgs84X,
COALESCE(realty.Wgs84Y, ruian_cobce.Wgs84Y, ruian_obec.Wgs84Y) as Wgs84Y,
realty.Ranking,
...
FROM realty
JOIN Category ON realty.CategoryId = Category.Id
LEFT JOIN ruian_cobce ON realty.cobceId = ruian_cobce.cobce_kod
LEFT JOIN ruian_obec ON realty.obecId = ruian_obec.obec_kod
LEFT JOIN okres ON realty.okresId = okres.okres_kod
LEFT JOIN ExternFile ON realty.Id = ExternFile.ForeignId AND …Run Code Online (Sandbox Code Playgroud) 我正在跟进有关计算列中奇怪值的问题PERSISTED。那里的答案对这种行为是如何产生的做出了一些猜测。
我在问以下问题:这不是一个彻头彻尾的错误吗?被PERSISTED列曾经允许这样的行为?
DECLARE @test TABLE (
Col1 INT,
Contains2 AS CASE WHEN 2 IN (Col1) THEN 1 ELSE 0 END PERSISTED) --depends on Col1
INSERT INTO @test (Col1) VALUES
(ABS(CHECKSUM(NEWID()) % 5)),
(ABS(CHECKSUM(NEWID()) % 5)),
(ABS(CHECKSUM(NEWID()) % 5)),
(ABS(CHECKSUM(NEWID()) % 5)),
(ABS(CHECKSUM(NEWID()) % 5))
SELECT * FROM @test --shows impossible data
UPDATE @test SET Col1 = Col1*1 --"fix" the data by rewriting it
SELECT * FROM @test --observe fixed data
/*
Col1 Contains2
2 0 …Run Code Online (Sandbox Code Playgroud) 我有Address一个名为 的表,它有一个名为 的持久计算列Hashkey。该列是确定性的,但不精确。它有一个不可查找的唯一索引。如果我运行这个查询,返回主键:
SELECT @ADDRESSID= ISNULL(AddressId,0)
FROM dbo.[Address]
WHERE HashKey = @HashKey
Run Code Online (Sandbox Code Playgroud)
我得到这个计划:

如果我强制索引,我会得到更糟糕的计划:

如果我尝试同时强制索引和查找,则会出现错误:
由于此查询中定义的提示,查询处理器无法生成查询计划。在不指定任何提示且不使用的情况下重新提交查询
SET FORCEPLAN
这仅仅是因为它不精确吗?我以为坚持就无所谓了?
有没有办法在不使其成为非计算列的情况下使该索引可查找?
有没有人有任何有关此信息的链接?
我无法发布实际的表创建,但这里有一个具有相同问题的测试表:
drop TABLE [dbo].[Test]
CREATE TABLE [dbo].[Test]
(
[test] [VARCHAR](100) NULL,
[TestGeocode] [geography] NULL,
[Hashkey] AS CAST(
( hashbytes
('SHA',
( RIGHT(REPLICATE(' ', (100)) + isnull([test], ''), ( 100 )) )
+ RIGHT(REPLICATE(' ', (100)) + isnull([TestGeocode].[ToString](), ''), ( 100 ))
)
) AS BINARY(20)
) PERSISTED
CONSTRAINT [UK_Test_HashKey] UNIQUE NONCLUSTERED([Hashkey])
)
GO
DECLARE @Hashkey …Run Code Online (Sandbox Code Playgroud) index sql-server optimization sql-server-2012 computed-column
我想根据两列是否相等进行快速查找。我尝试使用带有索引的计算列,但 SQL Server 似乎没有使用它。如果我只使用带有索引的静态填充位列,我会得到预期的索引查找。
似乎还有其他一些类似的问题,但没有一个关注为什么不使用索引。
测试表:
CREATE TABLE dbo.Diffs
(
Id int NOT NULL IDENTITY (1, 1),
DataA int NULL,
DataB int NULL,
DiffPersisted AS isnull(convert(bit, case when [DataA] is null and [DataB] is not null then 1 when [DataA] <> [DataB] then 1 else 0 end), 0) PERSISTED ,
DiffComp AS isnull(convert(bit, case when [DataA] is null and [DataB] is not null then 1 when [DataA] <> [DataB] then 1 else 0 end), 0),
DiffStatic bit not null,
Primary …Run Code Online (Sandbox Code Playgroud) computed-column ×10
sql-server ×9
index ×2
view ×2
functions ×1
index-tuning ×1
null ×1
optimization ×1
parallelism ×1
postgresql ×1