背景:
我是一名开发人员,正在开发一个应用程序,该应用程序有一个相对较大的表(至少根据我的经验),包含 17 亿条记录。
该表是历史表,应用程序每天都会导入到该表中。平均每天将插入大约 120 万条记录。
是的,那里有很多历史,不,不应该全部同时在线。
该表未分区。
该表包含报告日期列和货币列等,但这些是主要的逻辑“分区”列(如果您可以这样称呼它们)。
该表在 (ID, ReportDate) 上有一个聚集索引,在 ReportDate、Currency 和其他几个列上有一个非聚集索引。
今天,我的任务是解决一个应用程序问题,其中按报告日期和货币进行删除时命令超时。我无法检索删除整个记录集(大约 120 万行)的执行计划。我删除了 10k 条记录,花了 54 秒。
在开发一个也处理大型表的完全独立的应用程序时,我发现一个场景,表足够大,自动统计更新的阈值高于插入表中的记录数,因此对新插入的数据进行查询没有包含在统计中,因此任何查询都假设有 1 条记录(根据执行计划),因此 SQL 选择对数百万条记录使用嵌套循环连接。
实际问题:
统计信息对于 SQL 实际执行删除操作的方式有影响吗?
我的团队在最近的记忆中拥有统计经验,因此他们问我是否可能相关,我的直觉说“可能不会”,因为这次删除中没有涉及超时的连接。
我继续更新表上的统计信息(特别是索引上的统计信息),然后再次运行删除,批量删除 10k 记录需要 54 秒,减少到统计信息更新后的 18 秒。所以那里存在相关性。但是,该数据库位于与许多其他数据库共享的服务器上,因此我无法隔离它并说“是的,统计数据有帮助”,而这可能只是因为服务器在删除超时时很忙,而现在当再次尝试时,它就不那么忙了。
在尝试排除故障时,我查看了活动监视器,发现该进程经常等待 PAGEIOLATCH_SH,并且 I/O 非常低,低于 3MB/秒。