问题描述
最近一段时间后,我们将sql Server的兼容性级别从110(sql server 2012)更改为150(2019),
我们正在观察一个查询,它变得非常慢并且超时。该查询涉及以下2个表:
CREATE TABLE [Workflow].[Transaction](
[TransactionId] [uniqueidentifier] NOT NULL,[StartDate] [datetimeoffset](7) NOT NULL)
CREATE TABLE [Workflow].[TransactionData](
[Id] [bigint] IDENTITY(1,1) NOT NULL,[TransactionId] [uniqueidentifier] NOT NULL,[Date] [datetimeoffset](7) NOT NULL,[StateId] [int] NOT NULL)
每个订单交易记录都保存在[Workflow].[Transaction]
的100M行中,这些行是交易通过的状态,例如“开始”,“进行中”,“成功”,“失败”保存在[Workflow].[TransactionData]
200M行中。
[Workflow]。[Transaction] .StartDate上的Clusterdindex,大多数情况下,查询是根据时间范围完成的。 TransactionId上的非聚集索引。
TransactionData
在TransactionId中也有一个非集群索引,其中StateId和Date为包含列,
SELECT
T.TransactionId,LastState.StateId,T.StartDate
FROM Workflow.[Transaction] T
CROSS APPLY (
SELECT
TOP 1
StateId
FROM Workflow.[TransactionData] td
WHERE td.TransactionId = t.TransactionId
ORDER BY [Date] DESC,StateId DESC
) LastState
WHERE
@startDate <= t.StartDate
AND t.StartDate < @endDate
ORDER BY T.StartDate asc
使用兼容性级别150,并且基本上使用2014年发布的新基数运算符,由于估算非常错误,因此查询花费了很长时间,因此计划很糟糕。索引假脱机190M行。您可以看到完整的计划here。
OPTION (USE HINT ('FORCE_LEGACY_CARDINALITY_ESTIMATION'))
我们得到了更好的估算和计划。您可以看到完整的计划here。
看到这一点,我们检查了两个表的统计信息,它们都在1天之内更新了。
运行简单的select时,问题更加明显
SELECT
TransactionId
FROM Workflow.[Transaction]
where StartDate >= '2020-11-05 00:00:00 +02:00' and
StartDate < '2020-11-06 00:00:00 +02:00'
估计:7791,实际108855。查询计划可见here。 如果我们再次通过HINT启用传统基数运算符,则会得到更好的估计:131315(82%)。可以看到新的查询计划here。
集群索引统计的要点:
Histogram Steps
RANGE_HI_KEY RANGE_ROWS EQ_ROWS disTINCT_RANGE_ROWS AVG_RANGE_ROWS
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
10/27/2020 2:58:32 AM +02:00 731904.2 1 727784 1.005661
10/31/2020 12:14:20 PM +02:00 470738 1 468159 1.005508
11/6/2020 3:40:41 PM +02:00 805856.3 1 802208 1.004547
为什么新的基数运算符会对看起来很琐碎的情况做出如此糟糕的估计?
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)