我在虚拟服务器(128 GB,12 个虚拟处理器)上有 4 个开发 SQL Server 2016 实例。每个实例都配置相同(16 GB 内存、自动处理器和 I/O 关联掩码)。所有实例参数都相同。每个实例都有一个名为“operations”的数据库和一个名为“ErrLog”的表,表中有聚簇 PK 索引;每个实例的ErrLog目前有600-1000条记录。每个操作数据库在 E: 驱动器上有一个数据文件,在 F: 驱动器上有一个 tx 日志文件。在实例 (b)、(c) 和 (d) 中查询 ErrLog 表是亚秒级的。在实例 (a) 中,它始终需要 2-4 秒。
我进行典型的维护(每周一次 Ola Hallengren 的索引和统计维护),但每次都始终如一地进行。
我使用过 sp_BlitzFirst 和 sp_Blitz,它们返回问题,但实例之间存在一致的问题。到目前为止,我没有注意到各种 checkdb 操作返回的任何问题。
任何人都可以建议其他故障排除步骤来确定实例 (a) 的性能与其他实例不同的原因吗?(查询 ErrLog 只是磨练差异的代理;其他查询也有不同的表现。)
另外,我将a.Operations的副本恢复到b.Operations_test中,查询b.Operations_test.ErrLog也需要2-4秒。我将 b.Operations 的副本恢复到 a.Operations_test 中,查询 a.Operations_test 是亚秒级的。
编辑:感谢您的回复...
这是表格的结构(在每个实例中都相同);只有一个,聚簇主键索引:
CREATE TABLE [dbo].[ErrLog](
[ErrorID] [int] IDENTITY(1,1) NOT NULL,
[TimestampCreate] [dbo].[TimestampCreate] NOT NULL,
[ErrorNumber] [int] NOT NULL,
[ErrType] [int] NOT NULL,
[ErrLocation] [varchar](2000) NULL,
[ErrContext] [text] NULL,
[ErrSeverity] [int] NOT NULL,
[MessageLong] [varchar](1024) NOT NULL,
[ServerName] [dbo].[DescriptionLong] NULL,
CONSTRAINT [PK_ErrLog] PRIMARY KEY CLUSTERED
(
[ErrorID] ASC
)
PasteAPlan 结果:
这可能是不同性能的线索:我发现在 NP02 中,一些记录在 ErrContext 文本字段中具有更长的值:
NP02:668行;“ErrContext”文本字段的最大长度为 3,090,039
NP03:648 行;“ErrContext”文本字段的最大长度为 154,013
NP04:411 行;“ErrContext”文本字段的最大长度为 28,519
NP05:46 行;“ErrContext”文本字段的最大长度为 55,445
前 10 名等待统计数据(使用 Pinal Dave 的查询提取):
NP02:
等待类型 | Wait_Time_Seconds | Waiting_Tasks_Count | 百分比_等待时间 |
---|---|---|---|
OLEDB | 17951.078 | 1006510364 | 34.22289012 |
备份缓冲区 | 5775.054 | 6016680 | 11.00987018 |
ASYNC_IO_COMPLETION | 5491.216 | 3688 | 10.46874632 |
备份 | 5441.588 | 5592972 | 10.37413286 |
IO_COMPLETION | 3451.687 | 1192286 | 6.58047973 |
SOS_SCHEDULER_YIELD | 3271.515 | 6502869 | 6.236990244 |
PAGEIOLATCH_SH | 3191.304 | 2482244 | 6.084071726 |
备份线程 | 2224.763 | 229830 | 4.241406543 |
跟踪写入 | 1680.446 | 864 | 3.203691656 |
NP03:
等待类型 | Wait_Time_Seconds | Waiting_Tasks_Count | 百分比_等待时间 |
---|---|---|---|
CXP数据包 | 60954.838000 | 24948490 | 20.506848003464389 |
备份缓冲区 | 58801.396000 | 27540692 | 19.782372158277558 |
ASYNC_IO_COMPLETION | 48562.138000 | 1528 | 16.337610194112273 |
备份 | 41613.771000 | 28454440 | 13.999992531322523 |
OLEDB | 27122.218000 | 1397826908 | 9.124644085557670 |
备份线程 | 22593.140000 | 1078602 | 7.600940353594105 |
ASYNC_NETWORK_IO | 12203.635000 | 1545004 | 4.105631254975333 |
PAGEIOLATCH_SH | 8875.883000 | 5384558 | 2.986085921145972 |
SOS_SCHEDULER_YIELD | 5326.097000 | 43211882 | 1.791842374032848 |
IO_COMPLETION | 3153.986000 | 1708478 | 1.061085774800265 |
从执行计划中,我们可以看出重要的区别在于执行 ASYNC_NETWORK_IO 等待所花费的时间。对于你的慢速场景,你做了超过 14,000 个,但在你的快速场景中只有 159 个。
这就是说你的执行速度较慢必须对你的数据库进行更多的来回访问才能将所有数据发送到你的客户端。最明显的解释是
text
专栏。这个 lob 列的大小越大,客户端必须执行的读取请求就越多才能到达它的末尾。Lob 不像其他数据类型那么简单,它们的内容不一定适合与其余列相同的页面,因此使用指针代替。您的客户收到此指针并进行自己的查找。这可能导致每行多次查找(如您的情况),因为必须遵循进一步的指针。您应该阅读这篇文章以获取有关如何处理 lob 的更多信息https://aboutsqlserver.com/2013/11/05/sql-server-storage-engine-lob-storage/