小编liv*_*son的帖子

优化 CTE 层次结构

下面更新

我有一个具有典型帐户/父帐户体系结构的帐户表来表示帐户层次结构(SQL Server 2012)。我使用 CTE 创建了一个 VIEW 来散列层次结构,总的来说它工作得很好,而且符合预期。我可以查询任何级别的层次结构,并轻松查看分支。

有一个业务逻辑字段需要作为层次结构的函数返回。每个帐户记录中的一个字段描述了企业的规模(我们将其称为 CustomerCount)。我需要报告的逻辑需要从整个分支汇总 CustomerCount。换句话说,给定一个帐户,我需要将该帐户的 customercount 值与层次结构中帐户下方每个分支中的每个子项相加。

我使用 CTE 中构建的层次结构字段成功计算了该字段,该字段看起来像 acct4.acct3.acct2.acct1。我遇到的问题只是让它运行得很快。如果没有这个计算字段,查询会在大约 3 秒内运行。当我添加计算字段时,它变成了一个 4 分钟的查询。

这是我能想出的最好的版本,它返回正确的结果。我正在寻找有关如何在不牺牲性能的情况下重新构建此视图的想法。

我理解这个变慢的原因(需要在 where 子句中计算一个谓词),但我想不出另一种方法来构造它并且仍然得到相同的结果。

下面是一些示例代码,用于构建表并执行 CTE,这与它在我的环境中的工作方式几乎完全一样。

Use Tempdb
go
CREATE TABLE dbo.Account
(
   Acctid varchar(1) NOT NULL
    , Name varchar(30) NULL
    , ParentId varchar(1) NULL
    , CustomerCount int NULL
);

INSERT Account
SELECT 'A','Best Bet',NULL,21  UNION ALL
SELECT 'B','eStore','A',30 UNION ALL
SELECT 'C','Big Bens','B',75 UNION ALL
SELECT 'D','Mr. Jimbo','B',50 UNION ALL
SELECT 'E','Dr. John','C',100 UNION ALL
SELECT 'F','Brick','A',222 UNION …
Run Code Online (Sandbox Code Playgroud)

sql-server optimization cte sql-server-2012

15
推荐指数
2
解决办法
2446
查看次数

CASE 语句和 SARGability - 特定用例

编辑:SQL Server - 我希望这是一个足够通用的问题,我不需要指定版本,但我使用的大多数实例都是 2012 或更高版本。

我不够好,无法模拟数据并实际测试它,所以我希望有人可以查看它并以简单的经验回答。

想象一下,您有一个州表,其中的一列包含美国州的缩写(并且已编入索引,就像一个很好的查找列)。在编写临时查询时,用户通常会点击此列进行过滤,但使用的条件表示数据库中未隐含的信息。

例如,如果他们想要获得“大状态”,他们可能会在他们的即席查询中包含一个过滤器,显示类似

...
where
  StateAbbreviation in ('AK', 'TX')
Run Code Online (Sandbox Code Playgroud)

又名可怕的“商业规则”

所以这个查询很好,它执行得很好,并且利用了索引。但是,伙计,每次我们需要查询“大国”时,写下来真是太糟糕了。我很想在它的定义中使用这个过滤器创建一个视图,以使其更容易使用。

这里的问题是,这些业务规则特定于一些支持业务线的即席查询,但实际上并没有普遍用途。因此,创建一个以这种方式过滤数据的视图将没有什么用处。

因此,我想编写一个计算条件结果的视图,而不是编写该条件在过滤器中的视图,例如

select 
  StateAbbreviation
  , IsBig = case when StateAbbreviation in ('AK' , 'TX') then 1 else 0 end
from tblStates
Run Code Online (Sandbox Code Playgroud)

现在,当他们想为大州写一个查询时,他们只需要包括

where IsBig = 1
Run Code Online (Sandbox Code Playgroud)

在查询中。

所以,我的问题很简单 - 如果使用该条件调用视图,是否可以使用 StateAbbreviation 上的索引?

我知道我可以在 CASE 语句中做各种可能会改变答案的事情,所以为了回答这个非常具体的问题,假设 case 语句看起来只会像那样。它不会使用多个字段,也不会聚合 - 只是简单的文字输入或输出计算,以更简单的方式向报告编写者公开复杂的过滤条件。

performance index sql-server t-sql execution-plan

5
推荐指数
3
解决办法
1138
查看次数