Fre*_*gen 5 performance sql-server sql-server-2016 cardinality-estimates query-performance
在 SQL Server 2016 SP2 上,我们有一个查询对嵌套循环运算符的估计非常低。由于估计值较低,此查询也会溢出到 tempdb。
如果我是正确的,SQL Server 2014+ 使用粗直方图估计来计算连接的估计行数。
但是当我执行查询时,SQL Server 使用密度向量来计算估计的行数。如果没有子句,
SQL Server 是否仅使用粗直方图估计where
?
通常,当我有一个包含倾斜数据的表时,我会使用过滤的统计数据来改进估计。但在这种情况下,这似乎不起作用。
有没有办法改进嵌套循环的估计?
使用以下代码可以重现数据:
create table MyTable
(
id int identity,
field varchar(50),
constraint pk_id primary key clustered (id)
)
go
create table SkewedTable
(
id int identity,
startdate datetime,
myTableId int,
remark varchar(50),
constraint pk_id primary key clustered (id)
)
set nocount on
insert into MyTable select top 1000 [name] from master..spt_values
go
insert into SkewedTable select GETDATE(),FLOOR(RAND()*(1000))+1,REPLICATE(N'A',FLOOR(RAND()*(40))+1)
go 1000
insert into SkewedTable select GETDATE(),FLOOR(RAND()*(1000))+1,REPLICATE(N'A',FLOOR(RAND()*(40))+1)
go
CREATE NONCLUSTERED INDEX [ix_field] ON [dbo].[MyTable]([field] ASC)
go
CREATE NONCLUSTERED INDEX [ix_mytableid] ON [dbo].[SkewedTable]([myTableId] ASC)
go
--95=varchar in sys.messages
set nocount off
;with cte as
(
select GETDATE() as startdate ,95 as myTableId, REPLICATE(N'B',FLOOR(RAND()*(40))+1) as remark
union all
select * from cte
)
insert into skewedtable select top 40000 * from cte
option(maxrecursion 0)
go
update statistics mytable with fullscan
go
update statistics skewedtable with fullscan
go
Run Code Online (Sandbox Code Playgroud)
通常,当我有一个包含倾斜数据的表时,我会使用过滤的统计数据来改进估计。但在这种情况下,这似乎不起作用。
您应该会发现以下过滤统计数据很有帮助:
CREATE STATISTICS [stats id (field=varchar)]
ON dbo.MyTable (id)
WHERE field = 'varchar'
WITH FULLSCAN;
Run Code Online (Sandbox Code Playgroud)
这为优化器提供了有关匹配值分布的信息,从而为连接提供了更好的选择性估计:id
field = 'varchar'
上面的执行计划显示了过滤统计数据的准确估计,导致优化器选择散列连接(出于成本原因)。
这种分布信息比估计器用来匹配连接直方图(精细或粗略对齐)的精确方法,甚至一般假设(例如简单连接、基本包含)重要得多。
如果您不能这样做,那么您的选择大致如您之前的问题Sort splashs to tempdb 由于 varchar(max) 的回答中所述。我的偏好可能是中间临时表。