SQL数据库性能优化

mon*_*ona 7 performance sql-server-2008 sql-server performance-tuning

我们有一个写入量很大的 SQL 数据库(SQL Server 2008),一段时间后插入速度会降低。我阅读了这些类似的问题:Sql insert speed upSQL:如果不是 CPU 或 IO什么会降低插入速度加速插入

此外,我阅读了这篇关于如何分析 SQL Server 性能的文章,这有助于我了解如何找到瓶颈(例如,通过查询sys.dm_exec_requestssys.dm_os_wait_stats),但我仍然难以解释查询结果和解决问题。

首先,我开始查询sys.dm_exec_requests只返回一个状态为“正在运行”的会话 ID(选择查询)(即,我发现没有暂停会话)。那么,如果没有任何东西阻止我的插入,为什么它会变慢?

接下来,我曾经sys.dm_os_wait_stats检查有关所有等待类型的统计信息。结果显示LATCH_EX、CXPACKETPAGEIOLATCH_SHwait_time最长(分别为 694379 ms、310364 ms 和 308335 ms)。

然后我曾经sys.dm_os_latch_stats找到最流行的闩锁类型,在我的情况下是ACCESS_METHODS_DATASET_PARENT.

  • 首先,我不知道如何在查询的结果中找到与每个 session_id 相关的查询sys.dm_exec_requests
  • 其次,sys.dm_os_wait_stats应该将多少等待时间(in )视为高?如果上述数字(sys.dm_os_wait_stats 的结果)很高,我该如何减少它们?
  • 据我了解,ACCESS_METHODS_DATASET_PARENT与并行性有关,我发现的解决方案之一是降低并行度。那正确吗?
  • 在 MySQL 中,有一些可以在安装后立即完成的调整设置(例如,增加 innodb 缓冲池大小),SQL Server 中是否有类似的设置?

更多信息:

  • 使用sys.dm_db_index_usage_stats,读写次数分别为 80336 和 70672。

  • 我们最繁忙的表之一是trans_all(显示所有支付交易)没有触发器,没有约束(这对所有表都是一样的),但它有一个 CLUSTERED INDEX,即PK_trans_all 由以下列组成:gs_id(smallint), pt_id (tinyint)、fueling_time(datetime)、purchase_type(tinyint)。

  • 数据库大小为 2.6 GB,trans_all表大小为 155 MB。

更新_1

关于ACCESS_METHODS_DATASET_PARENT,我尝试了我找到的解决方案(即,更改并行度。我将其更改为 1 以确保查询永远不会进入并行度),但它没有解决问题:| 我应该再换一次吗?我应该使用的默认值是什么?

更新_2

我刚刚检查了我的数据库的事务日志文件的大小,它是2.4 GB,使用的 %log 空间是98%。这可能是放慢我插入速度的原因吗?我应该增加日志文件的大小吗?

此外,我过去常常sys.database_files检查文件大小以及数据库的空闲空间量。结果显示文件大小为195 MB,空白空间为0.187 MB

bwi*_*son 2

正如您所描述的,有许多因素可能导致插入速度减慢。

我在您的信息中没有看到插入数据的数据库/表大小。随着表的增长,由于表大小、碎片以及将相同数据写入索引,插入所需的时间也会越长。

您正在运行的 DM 查询为您提供了一些有用的信息。我还建议使用 Brent Ozar 的工具包。关联

我建议您使用 SP_BlitzIndex 和 SP_BlitzCache。这些将为您提供数据库中实际发生的情况以及您正在运行的插入查询当时正在执行的操作的另一个视图。

我还会检查上次运行 DBCC CHECKDB 的时间以及上次重建索引和统计信息的时间。

感谢您的更新,请参阅以下内容:

更多信息:

读/写量不是很大,所以我不太担心。

您知道上次重建 trans_all 索引是什么时候吗?如果只有一个覆盖索引,并且有很多次插入,如果数据已经过时,每次插入数据都会花费更长的时间。以下是检查数据库表碎片的查询:

Use <Database>
GO

SELECT OBJECT_NAME(ind.OBJECT_ID) AS TableName, 
ind.name AS IndexName, indexstats.index_type_desc AS IndexType, 
indexstats.avg_fragmentation_in_percent 
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, NULL) indexstats 
INNER JOIN sys.indexes ind  
ON ind.object_id = indexstats.object_id 
AND ind.index_id = indexstats.index_id 
WHERE indexstats.avg_fragmentation_in_percent > 30 
ORDER BY indexstats.avg_fragmentation_in_percent DESC
Run Code Online (Sandbox Code Playgroud)

更新1:

MAX DOP 设置可能会影响您的查询运行时间,但如果没有查看您正在使用的查询,然后查看估计的计划结果以了解 SQL Server 正在使用什么,我无法确定它是否会这样做。有两个统计数据可用于了解调整 MAX DOP 时查询受到的影响。

SET STATISTICS IO ON;
SET STATISTICS TIME ON;
GO
Run Code Online (Sandbox Code Playgroud)

以下是 Brent Ozar 的 Kendra Little 提供的一些有关使用这些信息为您提供指导的信息。

tsql-测量性能改进

q-can-high-maxdop-make-a-query-slower

更新2:

如果日志已满 98%,我建议增加日志大小。添加另一个传输日志或增加它。您还可以查看 TEMP_DB 并了解它在做什么,因为 SQL 使用它作为许多东西的垃圾场。

空旷的空间并不是真正的问题,除非你没有空间成长。它只是告诉您在下一次自动增长之前还剩下多少空间。