我有以下问题,我的 TempDB 知识还没有涵盖这一点:
- 在 SSMS 中运行约 200 毫秒的分析查询,从应用程序启动时在 SQL Server 上继续运行 60 秒以上 - 这种情况只是偶尔发生,大多数时候问题并不存在
- 可运行/挂起查询的队列可能会增长到同一查询文本的数十个查询,其中一个 SELECT 查询是阻止其他相同 SELECT 的头阻塞程序
- 当可运行/挂起队列与基线相比开始显着增长时,对于相同文本和参数值的特定查询,最主要的等待是 SOS_SCHEDULER_YIELD 和 PAGELATCH_UP
- 当问题发生时,排队的数十个查询具有相同的文字参数值(轮班开始时间戳、员工 ID 和生产区域)
- 被挂起的查询(在我们的监控快照期间 - DBA Dash)将 PAGELATCH_UP 等待作为最主要的等待,并且它们正在等待 tempdb 中的 GAM 页面
- 当我使用在可运行/挂起队列中不断堆积的查询参数检查 SSMS 中的执行计划时,查询不会溢出到 tempdb
服务器、数据库和数据库流量的配置:
- 4 到 6 个核心(问题独立发生在具有不同核心数的两台不同服务器上)
- 4 - 6 个大小统一的 TempDB 文件
- 分配给实例的 40GB RAM
- 在特定数据库中,启用了 RCSI + 快照(因此 TempDB 受到攻击)
- 运行查询的两个表上没有发生删除,只有 INSERT 和 SELECT - 当时仅插入 1 行
- SELECT 通常会命中最年轻的记录(最近插入的记录)
- 服务器通常每秒处理 400 - 700 个批量请求;当问题出现时,与正常操作相比,它会达到峰值 1500,从而产生较高的 IO + CPU 负载
- 表中的数据或多或少具有均匀分布,即特定生产区域的无班次中没有员工 ID 的记录明显多于其他员工
- 所附屏幕截图是一张表格,显示了问题完全显现时 DBA Dash 的快照
- tempDB,尽管 RCSI+ 快照增长不多,但在 60GB 驱动器上只有几 GB(稳定状态持续了几个月,并且在我在这里描述的几集之后)
- 屏幕截图中的所有 SELECT 查询都有 PAGELATCH_UP 等待,其中大约一半具有以下附加信息:
- 等待资源类型:PAGE
- 等待资源:2:3:2(我认为含义是:tempdb数据库,tempdb中的第三个文件,我们正在等待的第二页)
- 等待文件:主| 温度2
- 页面类型:GAM
- 等待编译:False
除了明显努力找到根本原因并永久解决它之外,我的主要问题是:
- 为什么 SELECT 查询可以大量访问 tempdb 中的 GAM 页面?
- 如果我承认 SELECT 可以频繁接触 GAM 页面,那么什么可以阻止查询(头拦截器)进行(即读取 GAM 页面并使其立即可供其他人使用)?
任何相关学习资源/建议的指针将不胜感激
编辑:为了回答约翰的评论,我想添加以下内容:
- CTFP:30
- MAXDOP:4(为两台 SQL 服务器设置,其中一个有 6 个核心,另一个有 4 个)
- 每个 SQL VM 有 2 个实例 - 发生问题的实例,然后是其他“办公室”实例,这对 SQL Server VM 造成的负载可以忽略不计
- 表格
ManualPanelEntries:6933089 条记录,1221 MB 数据,2591 MB 索引 - 事实上,索引比数据本身消耗更多空间
权重:3108486条记录,178MB数据,170MB索引
- 整个数据库:125GB
===========
写完这篇文章后我发现,头阻止程序(许多并行的相同 SELECT 之一)也在等待 GAM,即特定 tempdb 文件的第二页。就好像其他东西(版本存储?)在特定的 GAM 页面上持有锁定,阻止使用 TempDB 的其他查询继续进行。
减少 SQL Server tempdb 数据库中的分配争用的建议中的文档涵盖了问题的核心。您正在运行 SQL Server 2019,这意味着您将在 GAM 页面而不是 SGAM 上看到争用。
您的排序和散列操作可能不会溢出(尽管屏幕截图中的几个查询确实显示了写入),但 SQL Server 仍然必须分配结构(工作文件和工作表)来支持排序和散列,其中一些是必需的,以防出现运行时溢出。如果您足够快地执行足够多的这些操作,您可以看到 GAM 页锁存争用。
锁存器等待通常很短,但有可能遇到锁存器队列,有时会导致(很)长的等待。
如上面链接的文档中所述,主要解决方案是将文件添加到tempdb,直到争用消失或降低到可接受的水平。
可能与此处的具体问题无关,您还可以选择在 SQL Server 2019 中为tempdb启用内存优化元数据。该选项并非没有缺点,并且存在一些错误。
SQL Server 2022 引入了并发GAM 和 SGAM 更新,这用(共享)
UP
闩锁取代了(更新)SH
闩锁。这大大减少了此类问题的范围。选择查询通常不会阻止其他选择。我怀疑他们可能正在等待编译锁。
如果您在同一时间使用相同的参数值执行大量查询,则可能是您可以从应用程序端修复的问题。使用缓存。确保代码不存在导致查询执行频率超过必要频率的问题。例如,在循环内部而不是外部调用。
当您看到 tempdb GAM 争用时,我的第一个反应是检查我是否处于最近的补丁级别。已进行重大改进,以帮助解决各种 CU 中的 tempdb 争用问题。接下来我会考虑将临时数据库文件加倍。如果您有 6 个核心和 6 个文件,请将其加倍到 12 个。这可能超出了 tempdb 文件数量的默认准则,但如果您看到 tempdb GAM 争用,则更多文件会有所帮助。
我创建了 DBA Dash。希望你觉得它有用 ?