最近,我一直在优化大规模ERP数据包的性能。 我无法解决的性能问题之一涉及外键的基数估计错误,该外键仅限于来自大型表的一小部分记录。
表A包含3 mil记录并具有类型字段
表B保存7密耳记录并将外键FK保存到表A
外键只会填充表A中具有特定类型的主键,表A中3 mil记录中只有36个具有这种特定类型。
B JOIN A ON B.FK = A.PK AND A.TYPE = X AND A.Name = Y
现在使用正确的统计信息SQL知道表A只返回1个值
但SQL估计表B中只会返回2条记录(我猜是7密耳/ 3密耳),而实际返回930 000条记录 这导致使用缓慢的查询计划。
真正的查询更复杂,但错误查询计划的原因是因为这个简化的声明。
我们的数据库确实有FK的准确统计数据(直方图显示此FK的每个不同值的EQ_Rows),并且对固定的FK值进行过滤会导致准确的估计。
有没有办法向SQL显示这个FK只能保存少量不同的值,或以任何其他方式帮助他进行估算。
如果我们有机会将表格拆分并将这36条记录放在一个单独的表格中,但不幸的是这就是ERP系统的工作方式。
额外信息: 我们正在使用SQL 2014。 ERP系统是Dynamics AX 2012 R3 使用跟踪标志9481确实有帮助(不完美但更好)但遗憾的是我们无法使用Dynamics AX为单独的查询设置跟踪标志
答案 0 :(得分:0)
之前我遇到过这类问题,并且经常发现我可以通过将大表中的“极少数相关行”拉到一个小临时表中来大大减少存储过程或脚本的总运行时间,然后将该临时表加入主查询中。或者使用CTE查询来隔离所需的几行。一些实验应该很快告诉你这是否有可能在你的情况下。
答案 1 :(得分:0)
查看查询计划
显然你希望它早期过滤TYPE
它可能正在进行循环连接
FROM B
JOIN A
ON B.FK = A.PK
AND A.TYPE = X
AND A.Name = Y
尝试各种join hints
接下来将创建一个#temp并加入其中 在你临时宣告PK