AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 344001
Accepted
Frederik Vanderhaegen
Frederik Vanderhaegen
Asked: 2024-12-04 21:58:40 +0800 CST2024-12-04 21:58:40 +0800 CST 2024-12-04 21:58:40 +0800 CST

由于启用 querystore,需要进行大量日志备份

  • 772

我们有一台 SQL Server 2019 CU18,我们发现 querystore 存在一个奇怪的问题。通常,每小时日志备份的平均大小为 40MB,但一旦我们启用 querystore,日志备份的平均大小就会变成 2.5GB。

根据 querystore,每小时执行 140,000 个查询。这大约相当于每秒执行 40 次。

这是我们的查询存储的配置:

ALTER DATABASE [db_name]
SET QUERY_STORE = ON
    (
        OPERATION_MODE = READ_WRITE
        ,CLEANUP_POLICY = (STALE_QUERY_THRESHOLD_DAYS = 45)
        ,DATA_FLUSH_INTERVAL_SECONDS = 900
        ,MAX_STORAGE_SIZE_MB = 2048
        ,INTERVAL_LENGTH_MINUTES = 30
        ,SIZE_BASED_CLEANUP_MODE = AUTO
        ,QUERY_CAPTURE_MODE = AUTO
);

当我打开这么大的 logbackup 文件时,fn_dump_dblog我发现同一秒内发生了多个事务。这些事务都名为“SwapPage”。

手术 语境 分配单元编号 页面 ID 交易名称
LOP_BEGIN_XACT 空值 无效的 无效的 交换页面
LOP_INSYSXACT LCX_INDEX_INTERIOR 72057594047692800 0001:00056321 无效的
LOP_INSYSXACT LCX_CLUSTERED 72057594047692800 0001:000a871c 无效的
LOP_INSYSXACT LCX_CLUSTERED 72057594047692800 0001:0000041b 无效的
LOP_INSYSXACT LCX_CLUSTERED 72057594047692800 0001:0000041c 无效的
页面格式化 链接重组页面 72057594047692800 0001:000a8715 无效的
LOP_修改头 链接重组页面 72057594047692800 0001:000a8715 无效的
LOP_INSYSXACT LCX_CLUSTERED 72057594047692800 0001:000a8715 无效的
LOP_修改头 LCX_HEAP 72057594047692800 0001:000a871c 无效的
LOP_修改头 LCX_HEAP 72057594047692800 0001:0000041c 无效的
插入行 LCX_CLUSTERED 72057594047692800 0001:000a8715 无效的
LOP_修改头 LCX_HEAP 72057594047692800 0001:000a8715 无效的
LOP_修改头 LCX_HEAP 72057594047692800 0001:000a8715 无效的
LOP_修改_行 LCX_INDEX_INTERIOR 72057594047692800 0001:00056321 无效的
LOP_修改头 LCX_HEAP 72057594047692800 0001:0000041b 无效的
LOP_修改头 LCX_HEAP 72057594047692800 0001:0000041b 无效的
锁定迁移 空值 无效的 0001:000a8715 无效的
LOP_INSYSXACT LCX_CLUSTERED 72057594047692800 0001:000a8715 无效的
LOP_INSYSXACT LCX_CLUSTERED 72057594047692800 0001:0000041c 无效的
LOP_INSYSXACT 链接重组页面 72057594047692800 0001:0000041b 无效的
LOP_INSYSXACT LCX_CLUSTERED 72057594047692800 0001:000a871c 无效的
LOP_INSYSXACT LCX_INDEX_INTERIOR 72057594047692800 0001:00056321 无效的
提交XACT 空值 无效的 无效的 无效的

分配单元指向plan_persist_runtime_stats。

在Paul White的评论之后,我设置了一个扩展事件来捕获query_store_index_rebuild_started和query_store_index_rebuild_finished。令我惊讶的是,Querystore 正在进行索引重建。以下是此跟踪的结果:

事件 时间戳 当前大小
query_store_index_rebuild_started 2024-12-05 07:51:10.353 874208
查询存储索引重建已完成 2024-12-05 07:52:29.073 868832
query_store_index_rebuild_started 2024-12-05 08:20:58.497 873504
查询存储索引重建已完成 2024-12-05 08:22:18.320 869152
query_store_index_rebuild_started 2024-12-05 08:36:03.147 874528
查询存储索引重建已完成 2024-12-05 08:37:19.670 869664
query_store_index_rebuild_started 2024-12-05 09:06:00.943 874336
查询存储索引重建已完成 2024-12-05 09:07:12.750 870304

看起来索引重建在 874MB 左右开始,Querystore 的最大大小设置为 2048。

我还将事件的堆栈跟踪包含query_store_index_rebuild_started在扩展事件中。

sqllang!XeSqlPkg::CollectClientHostnameActionInvoke sqllang!XeSqlPkg::CollectDatabaseIdActionInvoke sqllang!XeSqlPkg::CollectDatabaseNameActionInvoke sqllang!XeSqlPkg
::CollectNtUsernameActionInvoke sqllang!XeSqlPkg::CollectSessionIdActionInvoke sqllang!XeSqlPkg::CollectTSqlStack<XE_ActionForwarder> sqllang!XeSqlPkg::CollectTSqlStackActionInvoke qds!XeQdsPkg::query_store_index_rebuild_started::Publish
qds!CDBQDS::ReclaimFreePages
qds!CDBQDS::DoSizeRetention
qds!CDBQDS::ProcessQdsBackgroundTask
qds!CQDSManager::AcquireGenericQdsDbAndProcess<<lambda_e51628d7833f66b5a045fa5bf2d27953>>
qds!CDBQDS::ProcessQdsBackgroundTask
sqldk!SOS_Task::Param::Execute
sqldk!SOS_Scheduler::RunTask
sqldk!SOS_Scheduler::ProcessTasks
sqldk!SchedulerManager::WorkerEntryPoint
sqldk!SystemThreadDispatcher::ProcessWorker
sqldk!SchedulerManager::ThreadEntryPoint
KERNEL32+0x17AC4
ntdll+0x5A8C1

我曾希望找到触发索引重建的原因,但没有那么幸运。

在Zikato的一些指导下,我在跟踪中添加了一些额外的查询存储相关事件。这表明,只有query_store_size_retention_cleanup_started发生事件时才会触发索引重建。

无需重建:
在此处输入图片描述

重建: 每次运行清理时都会删除 0KB,但显然需要重建。让我感到困惑的是清理事件的出现。我以为只有当 querystore 达到最大存储大小的 90% 时才会触发此事件。 增加 querystore 的最大大小没有任何区别。
在此处输入图片描述



有人遇到过同样的问题吗?有人能解释一下发生了什么吗?实例上的其他数据库没有这个问题。

sql-server
  • 3 3 个回答
  • 315 Views

3 个回答

  • Voted
  1. Paul White
    2024-12-05T23:01:04+08:002024-12-05T23:01:04+08:00

    在调试器下进行检查可以发现,查询存储在任何清理之后都会在其内部表上运行索引重组,无论是由大小还是年龄触发。

    调用堆栈

    这很有道理,因为清理的目的是为了释放空间。用户无法对内部 QDS 表进行维护。我们也无法禁用页面锁定,这是阻止重组运行的一种方法。

    因此,在 2019 年,你无法禁用这种重组行为;这只是查询存储所做的。这解释了日志增长。

    每次将查询存储数据保存到磁盘时,SQL Server 都会检查是否需要基于大小或基于时间的清理。基于大小的清理的 90% 阈值存储为变量值,而不是硬编码常量。这表明服务器可能会在某些条件下改变百分比。

    可以使用未记录的全局跟踪标志 7748 来阻止触发基于时间的清理。对于基于大小的清理,似乎没有类似的功能。

    无论触发条件如何,SQL Server 似乎总是首先尝试基于时间的清理(如果已启用,并且未设置跟踪标志)。这可能是因为基于时间的清理涉及的开销要少得多(无需根据针对内部表运行的相对昂贵的查询来决定要驱逐哪些查询)。

    奇怪的是,SQL Server 每隔 运行一次基于时间的清理INTERVAL_LENGTH_MINUTES。即使它没有发现任何要做的事情,之后仍然会执行索引重组。

    有一个未记录的跟踪标志可以防止索引重组,但它仅存在于 SQL Server 2022 中,而不存在于 SQL Server 2019 中。即使您正在运行 SQL Server 2022,您也需要联系 Microsoft 支持以获得使用新标志的授权。

    同时,您可以尝试使用未记录的跟踪标志 7748(或设置为零)禁用基于时间的清理STALE_QUERY_THRESHOLD_DAYS以进行正常操作,从而允许它在您可以容忍索引重组的期间运行。

    • 7
  2. Zikato
    2024-12-05T19:10:06+08:002024-12-05T19:10:06+08:00

    2GB 足以保存 45 天的查询存储数据吗?

    理想情况下,你应该避免基于大小的清理,正如 Kendra Little 的博客文章所言:基于大小的清理会导致性能问题 - 如何避免

    您可以尝试将最大存储大小加倍并查看重新索引频率是否下降吗?

    您还可以使用 XE 进行监控query_store_size_retention_cleanup_started,并检查它是否与query_store_index_rebuild_started

    • 5
  3. Best Answer
    Frederik Vanderhaegen
    2025-01-08T18:40:51+08:002025-01-08T18:40:51+08:00

    经过反复试验,我找到了解决该问题的方法。
    如果设置Stale_Query_Threshold_Days为 30,则重建过程每天仅触发几次。一旦我将其恢复为 45,它几乎每 20 分钟运行一次。

    我无法找到此问题的解释,但解决方法可以解决问题。

    • -1

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve