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

时间:2015-09-24 21:05:23

标签: sql sql-server sql-server-2008

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

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

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

2 个答案:

答案 0 :(得分: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);

有关如何使用的说明:帮助您通过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);

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

它的作用:通过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);

有关如何使用的说明: - 查看最后用户寻道时间,用户寻求帮助确定来源和重要性的数量 - 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);

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

这些应该可以帮到你!

我为那些感兴趣的人写了一篇关于这个主题here的博文。

答案 1 :(得分:3)

您应该使用SQL Server Profiler来跟踪哪些查询到达您的服务器。

然后使用Database Engine Tuning Advisor来测试每个查询。