运行 ETL 源查询时,SQL Server 2016 不断崩溃。内存开始以惊人的速度消耗然后达到最大值并且服务关闭。这看起来很荒谬,特别是因为查询在内存较少且磁盘较慢的 SQL Server 2014 上完美运行。<可能会发生什么变化,更重要的是,有没有办法在 2016 年更改服务器查询或内存设置以防止出现这种崩溃情况? 任何人都可以缩小问题范围(并确认它是一个错误)或提供更强大的解决方法吗?
MAXDOP 设置为 4,最小内存为 8000,最大为 24000,系统为 28GB。SQL 2014 机器上也运行了 SharePoint(不同的 SQL 实例),因此最大内存较低(12533mb)。SQL 2016 机器是完全相同的副本,只是它没有安装 SharePoint 并且已升级到 SSD。
该查询只有 9 列(6 个 INT),用于 7,122,737 条记录,带有两个小表连接和最少的过滤......查询没有任何改变,它再次在 SQL 2014 上完美运行。事实上,它运行得快了一分钟在 SQL 2014 与 SQL 2016 中,尽管有 SSD 和几乎两倍的内存添加,以实现本应更快的发布!
因此,经过大量搜索,恢复到数据库的多个不同安装仅安装在默认位置,我主要发现了这个问题。被散列的列之一是VARCHAR(MAX)
触发来自 的大量内存请求HASHBYTES
。并非完全不合理,尽管最长的列实际上只有 49 个字符。源系统......我认为解决方法是动态转换它。
如果 SQL Server 达到最大内存,它会通过此查询快速达到最大内存,它会崩溃。这似乎是偶然的,并且可能会产生其他错误,从而使服务器停止运行。添加 DISTINCT 可确保崩溃行为,除非存在过多的内存。
如果您有其他测试或想法或可以重现该问题,我已在此处创建了 Microsoft Connect 问题。我想说这只是部分答案,因为它仍然只是缩小到一系列可能性,我没有时间或能力完全识别。但是,这似乎不是一般的内存压力或一般 SQL 2016 设置和服务的结果。
以下可以重现该问题。
CREATE TABLE Testing (
VarCharMAX VARCHAR(MAX) NULL,
VarCharRealistic VARCHAR(100) NULL
) ON PRIMARY
GO
SELECT TOP 1000000
IDENTITY(INT, 1, 1) AS Number
INTO Numbers
FROM master.dbo.syscolumns x
CROSS JOIN master.dbo.syscolumns
GO --Ensure 1 million rows were inserted
INSERT INTO Testing
(VarCharMAX, VarCharRealistic)
SELECT
CAST(Number As VARCHAR(MAX)) + 'a' AS VarCharMAX
,CAST(Number As VARCHAR(100)) + 'a' AS VarCharRealistic
FROM Numbers
GO
--Server crash under ~16GB memory
SELECT DISTINCT
HASHBYTES('md5', VarCharMAX)
FROM dbo.Testing
我想我可能有一个合法的答案..它是一个错误。
(在 2014 年运行 checkdb 并在 SP1 + CU1 中修复时发现了类似情况)
当我按原样运行查询时,SQL Server 崩溃
在错误日志中我看到:
使用
OPTION (MAXDOP 1)
=> 串行执行请在您的环境中测试它并告诉我。