服务器 A 和服务器 B 具有相同的硬件和实例配置(A 是生产,B 是 QA)。B 的数据库是从 A 一周前的备份中恢复的。开发团队向我提供了这个查询。
SELECT
c.Start
,c.[End]
,c.Word
,doc.UniqueDocumentNumber
,doc.EID
,c.CUI
,c.Concept
,a.OID
,doc.DocumentTypeName
,doc.ActivityDtTm
,CAST(doc.DocumentTypeId AS INT) AS MedCode
,CASE WHEN c.[Count] = 0 THEN CAST(0.00 AS REAL)
ELSE CAST(LOG(c.TotalCount / c.[Count]) AS REAL) END AS 'idf'
,c.[Count]
,c.TotalCount
FROM ECHO..AEID201 a
INNER JOIN ALPHA..XADocuments doc (NOLOCK) ON a.EID = doc.EID
CROSS APPLY (SELECT t.start,t.[end],t.word,t.cui,t.eid,
t.UniqueDocumentNumber,cu.[Count],cc.TotalCount,core.Concept
FROM HOTEL.dbo.Htf_Index AS t
INNER JOIN HOTEL..Doc_CUI_Counter AS cu ON cu.CUI=t.CUI AND cu.DocumentTypeID=t.DocumentTypeID
INNER JOIN HOTEL..Doc_Counter AS cc ON cc.DocumentTypeID=t.DocumentTypeID
INNER JOIN HOTEL..CUI_CORE AS core ON core.CUI=cu.CUI
WHERE t.eid = doc.eid AND doc.UniqueDocumentNumber=t.UniqueDocumentNumber
) AS c
WHERE a.OID='00005159-9567-4187-a278-5b8e1e2ed20c'
AND ISNUMERIC(doc.DocumentTypeId) = 1
在服务器B上,查看执行计划表明,底部表[a]的条件是执行计划开始时索引查找操作的一部分,这使得子查询[c]结果集执行得很快。
在服务器 A 上,查看相同的执行计划表明,由于未应用外部条件,子查询 [c] 首先执行全索引扫描。
两个执行计划中使用的索引是相同的。自从正常操作恢复以来,服务器 A 上的表行数略多,但索引碎片几乎相同。服务器 B 的子查询中表 [t] 的参与索引的页数是服务器 A 的两倍,但行数相同。两台服务器上的统计信息每晚同时更新。
我已经尝试在表 [t] 上重建索引并手动更新统计信息以尝试使两个执行计划匹配。还有哪些其他因素可能导致执行顺序发生这种变化?
我建议开发人员用一个 UDF 替换子查询,该 UDF 将 [doc] 中的 EID 和 UniqueDocumentNumber 字段作为参数。我可以与开发人员一起探索哪些其他选项来增加 QA 执行计划在 Prod 上使用的可能性?
需要将执行计划(实际的,而不是估计的)添加到 Q 中以获得明确的答案,但是......
因为,据您承认,它们并不相同。对不同执行计划的最可能解释是统计数据的差异。
行计数不同,统计信息更新可能是默认样本,而不是
FULLSCAN
. 作为抽样的结果,我目睹了一些不幸的滑稽统计直方图,每个直方图都已通过FULLSCAN
更新得到纠正。