And*_*rei 5 performance sql-server statistics sql-server-2008-r2 query-performance
我正在尝试优化一个与此类似的查询:
select top(1)
t1.Table1ID,
t1.Column1,
t1....
....
t2.Table2ID,
t2....
....
c.FirstName,
c.LastName,
c....
from BigTable1 t1
join BigTable2 t2
on t1.Table1ID = t2.Table1ID
join Customer c
on t2.CustomerID = c.CustomerID
join Table4 t4
on t4.Table4ID = t2.Table4ID
join Table5 t5
on t5.Table5ID = t1.Table5ID
join Table6 t6
on t6.Table6ID = t5.Table6ID
where
t4.Column1 = @p1
and t1.Column1 = @p2
and t3.FirstName = @FirstName
and t3.LastName = @LastName
and t6.Column1 = @p5
and (@p6 is null or t2.Column6 = @p6)
order by t2.Table2ID desc
option(recompile);
Run Code Online (Sandbox Code Playgroud)
BigTable1、BigTable2、Customer - 是大型事务表(数亿行),Table4、Table5、Table6 是相对静态的小型查找表。问题是那些大表中的数据分布很不均衡,因此这个查询的性能通常很差(执行计划中的估计行数与实际行数非常不同)。更新这些大表的统计数据无济于事(直方图中的 200 步不足以覆盖数据分布中的所有偏差)。例如,在 Customer 表中,有一些(FirstName、LastName)组合对应于大约 500k 条记录。
我看到 2 个选项可以提高此类查询的性能:
为尖峰值创建过滤统计信息,例如对于 Customer 表,它看起来像这样:
declare @sql nvarchar(max) = N'', @i int, @N int;
select top (1000)
identity(int,1,1) as id,
FirstName,
LastName,
count(*) as cnt
into #FL
from Customer
where
FirstName is not null
and LastName is not null
group by
FirstName,
LastName
order by cnt desc;
set @N = @@ROWCOUNT;
set @i = 1;
while @i <= @N
begin
select @sql = 'CREATE STATISTICS Customer_FN_LN_' + cast(id as varchar(10)) + ' ON dbo.Customer(CustomerID) WHERE FirstName = ''' + FirstName + ''' AND LastName = ''' + LastName + ''' WITH FULLSCAN, NORECOMPUTE'
from #FL
where id = @i;
exec sp_executesql @sql;
set @i = @i + 1;
end;
Run Code Online (Sandbox Code Playgroud)因此,如果我们为这 3 个大表创建此过滤统计信息并重新创建这些统计信息,比如说,每周,我们应该可以在原始查询中进行行估计。
根据我以前的经验,我通常使用临时表的方法,但在这种情况下,过滤统计数据的方法看起来更有吸引力。不过,我还没有在生产中使用它,我很好奇它的缺点是什么。
所以我的问题是:
- 是否有其他方法可以帮助优化器处理高度倾斜的数据分布?
过滤统计信息和使用中间临时表分解查询(正确!)是主要选项,但您也可以考虑如何使用索引视图来提供帮助。如果正确实现,索引视图应该与基表上的额外非聚集索引具有大致相同的影响。
使用WITH (NOEXPAND)
而不是依赖自动匹配(仅限企业版)将允许优化器在索引视图上创建和使用统计信息。
更一般地说,如果您能够提前识别“安全”或“不安全”值,则可以考虑采用混合方法(包括动态 SQL),如Kimberly L. Tripp 的《构建高性能存储过程》中详细介绍的那样。
您还可以考虑针对不同情况优化多个单独的过程,在每个过程中使用适当的方法,包括诸如OPTIMIZE FOR
.
最后,您可以通过查询存储(如果可用)获得计划指南和/或强制计划。
- 在第二种方法中手动创建和处理过滤统计数据有哪些缺点?
主要问题是过滤后的统计数据没有像人们希望的那样频繁更新。您可以通过手动刷新这些统计信息来解决此问题。
您已经在重新编译,因此应该解决使用参数化查询过滤统计信息的问题。
当我读到你的问题时,我立即想到了过滤统计数据。问题是,如果查询被参数化,则无法使用它们,除非您提示重新编译。
查看 Erik Darling 的这篇好文章:https://www.brentozar.com/archive/2016/12/filtered-statistics-follow/
归档时间: |
|
查看次数: |
1402 次 |
最近记录: |