2017-08-25 31 views
0

我支持每天晚上运行的流程,并查看具有未付订单项的发票的各种客户。该流程从删除登台表中的所有记录开始,然后将多个发票行项目插入登台表中。该流程基于每个客户端运行,因此某些客户可能有200个订单项,某些客户可能有50,000个。我们在这个过程中经常遇到很多问题。这个问题似乎源于SQL Server无法估计当时登台表中正确的行数,因此会产生错误的执行计划。我的问题是,是否有办法手动设置估计的行数以提高存储过程的基数估计值?也许这可以在运行开始时通过选择计数(primaryKey)完成,在当前运行临时表填充之后立即执行?如何提高登台表上的基数估计值?

+1

如果您要删除并插入并且不从临时表中选择;为什么SQL会使用临时表中的统计数据?也许我错过了一些东西;但除非您正在执行选择或合并,并基于登台表中的数据进行插入/删除,为什么它的统计数据很重要?或者你是在删除/插入完成后说话,那么你在分段表上进行分析很慢?你是否在表格/索引视图上试过强制更新? https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-updatestats-transact-sql – xQbert

+1

在进程启动之前,您可以尝试更新表上的统计信息。 https://docs.microsoft.com/en-us/sql/t-sql/statements/update-statistics-transact-sql。更新统计信息后,您可以重新编译任何存储过程以强制SQL提出新的执行计划。 https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-recompile-transact-sql – Jason

+1

删除所有行并重新填充它将导致统计信息被更新。也许你遇到参数嗅探,其中不同的客户端有很大的不同行数,但是这个计划是为遇到的第一个客户端编译的。在这种情况下,将“OPTION(RECOMPILE)”添加到问题查询中会有所帮助。 –

回答

1

您正在此表上执行大批量进程。在批次之前删除所有索引并在批次之后再次创建它们是一种好方法。

如果你这样做,你的统计数据将被更新,而不会成为你的问题的原因。

还需要注意统计信息的更一般信息:更新统计信息在SQL Server 2014和SQL Server 2016之间有很大变化。如果您运行的是SQL Server 2016,则需要检查数据库是否使用新基数估计器为SQL Server 2016创建。请检查您的数据库是否正在运行SQL Server 2016兼容级别。

如果您正在运行SQL Server 2014,一个不错的选择是启用跟踪标志2371.此跟踪标志改进了SQL Server用于自动更新统计信息的标准。您应该使用SQL Server配置管理器来启用此跟踪标志。

但是,如果您按照第一个建议删除并创建索引,那么另外两个建议的影响就会很小或没有影响。

+0

为什么要删除并重新创建索引而不是禁用并重建它们? – alroc

+0

Sql Server 2008. –

+1

@alroc如果禁用聚簇索引,表将变为只读。 –