gar*_*rik 7 performance sql-server-2008 query aggregate materialized-view
我有两个表:详细信息和这些详细信息的总计。
详细信息(缓慢的解决方案):
select
OrderId = r.OrderId
, TotalQty = SUM(r.Quantity)
, TotalGrossConsid = SUM(r.Price * r.Quantity)
from dbo.Order r
group by r.OrderId
Run Code Online (Sandbox Code Playgroud)
总计(快速解决方案):
select
t.OrderId
, t.TotalQty
, t.TotalGrossConsid
, t.IsValid
from dbo.OrderTotal t
Run Code Online (Sandbox Code Playgroud)
有时总数变得无效(某些作业必须重新计算更改的总数,但会延迟)。如您所知,第二个查询更快,有效总数的数量多于无效总数。因此,我正在寻找一个组合查询,该查询从第二个表 (totals) 返回有效总数,并使用第一个慢查询返回动态重新计算的总数。所以我的目标将实现:所有总数都是有效的,响应时间比完全重新计算要快。
这是我的尝试(混合解决方案):
with fast_static(OrderId, TotalQty, TotalGrossConsid, IsValid)
as
(
select
t.OrderId
, t.TotalQty
, t.TotalGrossConsid
, t.IsValid
from dbo.OrderTotal t
)
, slow_dynamic(OrderId, TotalQty, TotalGrossConsid)
(
select
OrderId = r.OrderId
, TotalQty = SUM(r.Quantity)
, TotalGrossConsid = SUM(r.Price * r.Quantity)
from dbo.Order r
)
select
OrderId, TotalQty, TotalGrossConsid
from fast_static
where IsValid = 1
union all
select
OrderId, TotalQty, TotalGrossConsid
from slow_dynamic s
--inner join fast_static ff
--on ff.OrderId = s.OrderId
where --ff.Valid = 0 -- too slow!!!
s.OrderId in (select OrderId from fast_static f where f.Valid = 0)
Run Code Online (Sandbox Code Playgroud)
我比较了快速解决方案和混合解决方案,我得到了 32% 到 68%(相对查询成本)。如果您可以看到注释变体,则它等于 1% 到 99%(太糟糕了)。是否可以改进此查询?
添加
@gbn:
Valid = case when i.OrderId is null then 1 else 0 end
...
dbo.OrderTotal t left join dbo.InvalidOrders i
Run Code Online (Sandbox Code Playgroud)
是的,我有一项重新计算总数的工作,但此过程与查询请求不同步。InvalidOrders 表是一个小表,用于存储记录以了解总计无效(要重新计算)
解决方案
索引视图是最佳选择。请注意 SQL Server 版本(非企业版本的noexpand 提示)并准备好重新创建一些数据库对象( SET ANSI_NULLS ON, SET QUOTED_IDENTIFIER ON
) 以开始在客户端使用索引视图。
我不明白为什么你不能在飞行中聚合,为什么它这么慢。“有效”的想法是处理 OrderTotals 或某些业务流程滞后的解决方法吗?
这两种想法都放弃了 InvalidOrder 表,这是一种针对不良索引的解决方法。
创建计算列
ALTER TABLE dbo.Order ADD PriceXQuantity AS Price * Quantity PERSISTED
Run Code Online (Sandbox Code Playgroud)
添加索引
CREATE INDEX IX_Totals ON dbo.Order (OrderID) INCLUDE Quantity, PriceXQuantity)
Run Code Online (Sandbox Code Playgroud)
走着瞧吧
使用索引视图
CREATE VIEW OrderTotals
WITH SCHEMABINDING
AS
select
OrderId = r.OrderId
, TotalQty = SUM(r.Quantity)
, TotalGrossConsid = SUM(r.Price * r.Quantity)
, COUNT_BIG(*) AS Dummy
from dbo.Order r
group by r.OrderId
GO
CREATE UNIQUE CLUSTERED INDEX IXCU_OrderTotals ON OrderTotals (OrderId9
GO
Run Code Online (Sandbox Code Playgroud)
您也可以在此处使用计算列
归档时间: |
|
查看次数: |
2130 次 |
最近记录: |