如何解决SQL Server中的性能问题

Jas*_*ell 2 sql sql-server sql-server-2008

我有一个相对较大的数据库(每个表有数百万条记录),它有许多表和索引,这些表和索引是由以前的开发人员设置的,我正在努力找到解决一些性能问题的好方法.

我们的应用程序在其整个生命周期中进行了许多数据库调用,我试图找到一种很好的方法来诊断一些较慢的查询,或者我们缺少索引的一些实例,或者我们写入的表上有索引的索引.

有哪些快速查询可以让我对我正在寻找的内容有所了解?

Jas*_*ell 5

如果您不熟悉正在为您跟踪所有这些信息的SQL Server系统表,那么查找这些内容可能会非常麻烦.但是,希望通过探索下面列出的一些查询(针对最常见的问题),您会发现对特定问题的一些了解.

它的作用:按当前数据库的平均输入/输出使用情况列出顶部语句

SELECT TOP(50) OBJECT_NAME(qt.objectid) AS [SP Name],
(qs.total_logical_reads + qs.total_logical_writes) /qs.execution_count AS [Avg IO],
SUBSTRING(qt.[text],qs.statement_start_offset/2, 
               (CASE 
                              WHEN qs.statement_end_offset = -1 
                THEN LEN(CONVERT(nvarchar(max), qt.[text])) * 2 
                              ELSE qs.statement_end_offset 
                END - qs.statement_start_offset)/2) AS [Query Text]         
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS qt
WHERE qt.[dbid] = DB_ID()
ORDER BY [Avg IO] DESC OPTION (RECOMPILE);
Run Code Online (Sandbox Code Playgroud)

如何使用注意事项:帮助您找到SP最昂贵的I/O语句

它的作用:可能的坏NC索引(写入>读取)

SELECT OBJECT_NAME(s.[object_id]) AS [Table Name], i.name AS [Index Name], i.index_id,
user_updates AS [Total Writes], user_seeks + user_scans + user_lookups AS [Total Reads],
user_updates - (user_seeks + user_scans + user_lookups) AS [Difference]
FROM sys.dm_db_index_usage_stats AS s WITH (NOLOCK)
INNER JOIN sys.indexes AS i WITH (NOLOCK)
ON s.[object_id] = i.[object_id]
AND i.index_id = s.index_id
WHERE OBJECTPROPERTY(s.[object_id],'IsUserTable') = 1
AND s.database_id = DB_ID()
AND user_updates > (user_seeks + user_scans + user_lookups)
AND i.index_id > 1
ORDER BY [Difference] DESC, [Total Writes] DESC, [Total Reads] ASC OPTION (RECOMPILE);
Run Code Online (Sandbox Code Playgroud)

有关如何使用的说明: - 查找具有大量写入和零或极低读取次数的索引 - 考虑您的完整工作负载 - 在删除索引之前进一步调查

功能:通过Index Advantage缺少当前数据库的索引

SELECT user_seeks * avg_total_user_cost * (avg_user_impact * 0.01) AS [index_advantage], 
migs.last_user_seek, mid.[statement] AS [Database.Schema.Table],
mid.equality_columns, mid.inequality_columns, mid.included_columns,
migs.unique_compiles, migs.user_seeks, migs.avg_total_user_cost, migs.avg_user_impact
FROM sys.dm_db_missing_index_group_stats AS migs WITH (NOLOCK)
INNER JOIN sys.dm_db_missing_index_groups AS mig WITH (NOLOCK)
ON migs.group_handle = mig.index_group_handle
INNER JOIN sys.dm_db_missing_index_details AS mid WITH (NOLOCK)
ON mig.index_handle = mid.index_handle
WHERE mid.database_id = DB_ID() -- Remove this to see for entire instance
ORDER BY index_advantage DESC OPTION (RECOMPILE);
Run Code Online (Sandbox Code Playgroud)

关于如何使用的注意事项: - 查看上次用户搜索时间,用户寻求帮助确定源和重要性的数量 - SQL Server过于急于添加包含的列,所以要注意 - 不要盲目添加从此查询中显示的索引!

它的作用:获取当前数据库中超过一定大小的所有索引的碎片信息 - 注意:这可能需要一些非常大的数据库

SELECT DB_NAME(database_id) AS [Database Name], OBJECT_NAME(ps.OBJECT_ID) AS [Object Name], 
i.name AS [Index Name], ps.index_id, index_type_desc,
avg_fragmentation_in_percent, fragment_count, page_count
FROM sys.dm_db_index_physical_stats( NULL,NULL, NULL, NULL ,'LIMITED') AS ps
INNER JOIN sys.indexes AS i 
ON ps.[object_id] = i.[object_id] 
AND ps.index_id = i.index_id
WHERE database_id = DB_ID()
--AND page_count > 500
ORDER BY avg_fragmentation_in_percent DESC OPTION (RECOMPILE);
Run Code Online (Sandbox Code Playgroud)

有关如何使用的说明: - 帮助确定关系索引中是否存在碎片 - 以及索引维护策略的有效性

这些应该让你开始!

在这里为感兴趣的人写了一篇关于这个主题的博文.