SQL Server 速度变慢?

Mic*_*ael 4 performance sql-server

我们是一家小商店,从任何想象来看我都不是 DBA,但我最近继承了一个较大的旧数据库(至少从 04 年开始运行),在过去的一个月里,它经历了慢一点。它从我们更复杂的查询开始,但甚至开始影响更简单的查询。

在我同事离开之前,他已经将实例从 2008(标准)升级到 2014(企业)。这些文件也在数据库上缩小了,(我现在知道这是不赞成的。)但是,我相信实例在升级和缩小后直接运行良好。

我们有两个使用 AlwaysOn 设置的专用 SQL 服务器。这些服务器已经有大约 5 年的历史了,但它们仍然是很好的服务器(64GB 内存,Intel Xeon)。哪个是主要的并不重要,两者都会经历减速。服务器还有其他一些实例,但我正在尝试排除故障的实例是迄今为止最大的实例。其中一些实例是 Dev 和 Staging,它们都大约有一个月的历史。我一直在运行的查询在其中任何一个上都需要两分钟,但在现场需要 20-40 分钟。我试过实时复制到一个新实例,但它也很慢。

我试过重新启动实例、更新统计信息、刷新视图(我们并没有真正使用)、重建索引,但似乎没有任何帮助。有任何想法吗?

Ion*_*nic 6

那么这里有一个小清单。由于我不在您的机器上,因此我无法查看内部并给您一些建议。但我很确定,您会通过提供的语句找到根本原因。

错误的内存配置

正如您所提到的,您升级了 SQL Server 并在同一台物理机上运行不同的实例。可能有害的事情之一是重新启动或类似的事情(例如故障转移)。也许您的实例已重置其内存限制。这可能可以解释您的大幅放缓。您可以检查它们是否仍然符合您记录的最大内存。您可以让它们运行以下命令:

EXEC sp_configure N'max server memory (MB)'
Run Code Online (Sandbox Code Playgroud)

如果您只是想将其视为速记。您可以尝试查询dm_os_sys_memory有一个不错的列system_memory_state_desc,该列不是很详细,但它也说明了您需要的东西。如果您的内存不足,它会显示,这意味着系统上存在持续的内存压力。

SELECT system_memory_state_desc
FROM sys.dm_os_sys_memory
Run Code Online (Sandbox Code Playgroud)

统计数据已过时

您可能想要更新数据库表的统计信息,因为它们可能太旧了。

EXEC sp_updatestats
Run Code Online (Sandbox Code Playgroud)

在像您这样的情况下,丢弃缓存计划是明智的,因为由于旧的统计数据,它可能毫无用处。如果sp_updatestats显示许多表和许多更新的统计信息,最好将其丢弃并让 SQL Server 重新创建它。

您可以使用以下DBCC命令实现此目的:

DBCC FREEPROCCACHE
Run Code Online (Sandbox Code Playgroud)

碎片索引

可能是您的索引过于分散,从而导致 I/O 子系统的巨大负载。在盲目执行语句之前,您应该检查您的机器是否对您的 I/O 子系统有更高的负载。例如,这可以很容易地完成perfmon。本READ UNCOMMITTED应作为某些指标可能会在此刻被写入。您可以尝试运行以下语句。

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 

-- Get Index Fragmentation
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 > 25 
ORDER BY indexstats.avg_fragmentation_in_percent DESC
GO
Run Code Online (Sandbox Code Playgroud)

请注意,它可能会运行很长时间,并且在您已经承受压力的系统上可能会杀死它。如果您的系统可能会受到它的影响,请仅运行它。

将返回的每一行都是一个碎片化的索引,可能需要一个REBUILDor REORGANIZE。这也可能会提高您的整体系统性能,但在重建过程中,它会变慢!

ARITHABORT 问题

这可能是一个问题ARITHABORT,往往会在旧数据库上出现问题(对于某些用户)。也许您尝试启用/禁用它。

许多其他原因...

正如第一句话中提到的,很难看出你的问题在哪里。这可能是另一个错误 - 甚至可能是硬件故障。我在切换到我的 SAN 时遇到了一个错误,这也影响了我的性能多年(在它是多余的之前)。

但是,如果以上都没有帮助,您仍然可以提供您的输出,dm_os_wait_stats这可能有助于我正确了解您的系统。

SELECT TOP 30 *
FROM sys.dm_os_wait_stats
ORDER BY wait_time_ms DESC
Run Code Online (Sandbox Code Playgroud)

这将返回最大的等待计数器,并可能有助于找到瓶颈或错误。您可以使用以下查询执行此操作:

-- Show all active processes with detailed informations
SELECT pr.spid, pr.loginame, pr.status, pr.blocked, pr.waittime, pr.lastwaittype,pr.cpu, pr.physical_io, pr.memusage, pr.last_batch, db.name AS databaseName, obj.name AS objectName, txt.text AS currentQuery, pr.request_id
FROM sys.sysprocesses as pr
INNER JOIN sys.databases as db
        ON pr.dbid = db.database_id
OUTER APPLY sys.dm_exec_sql_text(pr.sql_handle) as txt
LEFT JOIN sys.all_objects as obj
        ON txt.objectid = obj.object_id
WHERE pr.status <> 'sleeping'
    and pr.spid >= 50
Run Code Online (Sandbox Code Playgroud)

此外,它可能是一个产生锁或消耗超过应有的锁的进程。但我认为这不是最好的可能性。但无论如何,您可以查看正在运行的进程。也许你看到了一些不正确的东西。