Ref*_*din 1 sql-server database-tuning sql-server-2008-r2
我们的主数据库大小为 15GB。服务器有 16GB RAM。我们使用简单的恢复模型。
最近,我们注意到我们的自定义应用程序查找(只是使用即席 SQL 语句进行基本读取)速度明显减慢。大多数情况下会多几秒钟。
我不是 SQL Server 管理员,并且不知道接下来该去哪里。
我们监控了CPU,它似乎从未达到峰值。与 RAM 相同。我们有大量的索引,但我认为这只是写入速度的问题......
对我下一步可以看什么有什么建议吗?
造成这种情况的原因可能有很多。几个问题:
选项 1 - 我们可以查看您的等待统计数据,看看这是否有助于确定查找方向。
选项 2 - 我们可以查看运行缓慢的查询的执行计划。
对于选项 1: 通过 Management Studio 运行此命令(它将运行 30 秒),点击“执行”后,在第二个选项卡中运行运行缓慢的查询之一,然后切换回上一个选项卡并将结果复制并粘贴到此处:
DECLARE @FinishSampleTime DATETIME
IF OBJECT_ID('tempdb..#WaitStats') IS NOT NULL
DROP TABLE #WaitStats;
CREATE TABLE #WaitStats
(
Pass TINYINT NOT NULL,
wait_type NVARCHAR(60),
wait_time_ms BIGINT,
signal_wait_time_ms BIGINT,
waiting_tasks_count BIGINT,
SampleTime DATETIME
);
-- Populate #WaitStats with DMV data. In a second, we'll compare these.
INSERT #WaitStats(Pass, SampleTime, wait_type, wait_time_ms, signal_wait_time_ms, waiting_tasks_count)
SELECT
1 AS Pass,
GETDATE() AS SampleTime,
os.wait_type,
SUM(os.wait_time_ms) OVER (PARTITION BY os.wait_type) as sum_wait_time_ms,
SUM(os.signal_wait_time_ms) OVER (PARTITION BY os.wait_type ) as sum_signal_wait_time_ms,
SUM(os.waiting_tasks_count) OVER (PARTITION BY os.wait_type) AS sum_waiting_tasks
FROM sys.dm_os_wait_stats os
WHERE
os.wait_type not in (
'REQUEST_FOR_DEADLOCK_SEARCH',
'SQLTRACE_INCREMENTAL_FLUSH_SLEEP',
'SQLTRACE_BUFFER_FLUSH',
'LAZYWRITER_SLEEP',
'XE_TIMER_EVENT',
'XE_DISPATCHER_WAIT',
'FT_IFTS_SCHEDULER_IDLE_WAIT',
'LOGMGR_QUEUE',
'CHECKPOINT_QUEUE',
'BROKER_TO_FLUSH',
'BROKER_TASK_STOP',
'BROKER_EVENTHANDLER',
'SLEEP_TASK',
'WAITFOR',
'DBMIRROR_DBM_MUTEX',
'DBMIRROR_EVENTS_QUEUE',
'DBMIRRORING_CMD',
'DISPATCHER_QUEUE_SEMAPHORE',
'BROKER_RECEIVE_WAITFOR',
'CLR_AUTO_EVENT',
'DIRTY_PAGE_POLL',
'HADR_FILESTREAM_IOMGR_IOCOMPLETION',
'ONDEMAND_TASK_QUEUE',
'FT_IFTSHC_MUTEX',
'CLR_MANUAL_EVENT',
'SP_SERVER_DIAGNOSTICS_SLEEP',
'HADR_CLUSAPI_CALL',
'HADR_LOGCAPTURE_WAIT',
'HADR_TIMER_TASK',
'HADR_WORK_QUEUE'
)
ORDER BY sum_wait_time_ms DESC;
-- Wait for the specified amount of time
SET @FinishSampleTime = DATEADD(second,30,GETDATE());
WAITFOR TIME @FinishSampleTime;
-- Populate #WaitStats with DMV data. In a second, we'll compare these.
INSERT #WaitStats(Pass, SampleTime, wait_type, wait_time_ms, signal_wait_time_ms, waiting_tasks_count)
SELECT
2 AS Pass,
GETDATE() AS SampleTime,
os.wait_type,
SUM(os.wait_time_ms) OVER (PARTITION BY os.wait_type) as sum_wait_time_ms,
SUM(os.signal_wait_time_ms) OVER (PARTITION BY os.wait_type ) as sum_signal_wait_time_ms,
SUM(os.waiting_tasks_count) OVER (PARTITION BY os.wait_type) AS sum_waiting_tasks
FROM sys.dm_os_wait_stats os
WHERE
os.wait_type not in (
'REQUEST_FOR_DEADLOCK_SEARCH',
'SQLTRACE_INCREMENTAL_FLUSH_SLEEP',
'SQLTRACE_BUFFER_FLUSH',
'LAZYWRITER_SLEEP',
'XE_TIMER_EVENT',
'XE_DISPATCHER_WAIT',
'FT_IFTS_SCHEDULER_IDLE_WAIT',
'LOGMGR_QUEUE',
'CHECKPOINT_QUEUE',
'BROKER_TO_FLUSH',
'BROKER_TASK_STOP',
'BROKER_EVENTHANDLER',
'SLEEP_TASK',
'WAITFOR',
'DBMIRROR_DBM_MUTEX',
'DBMIRROR_EVENTS_QUEUE',
'DBMIRRORING_CMD',
'DISPATCHER_QUEUE_SEMAPHORE',
'BROKER_RECEIVE_WAITFOR',
'CLR_AUTO_EVENT',
'DIRTY_PAGE_POLL',
'HADR_FILESTREAM_IOMGR_IOCOMPLETION',
'ONDEMAND_TASK_QUEUE',
'FT_IFTSHC_MUTEX',
'CLR_MANUAL_EVENT',
'SP_SERVER_DIAGNOSTICS_SLEEP',
'HADR_CLUSAPI_CALL',
'HADR_LOGCAPTURE_WAIT',
'HADR_TIMER_TASK',
'HADR_WORK_QUEUE'
)
ORDER BY sum_wait_time_ms DESC;
----------------------------
-- What happened: #WaitStats
----------------------------
;with max_batch as (
select max(SampleTime) as SampleTime
from #WaitStats
)
SELECT
'WAIT STATS' as Pattern,
b.SampleTime as [Sample Ended],
datediff(ss,wd1.SampleTime, wd2.SampleTime) as [Seconds Sample],
wd1.wait_type,
c.[Wait Time (Seconds)],
c.[Signal Wait Time (Seconds)],
(wd2.waiting_tasks_count - wd1.waiting_tasks_count) AS [Number of Waits]
FROM max_batch b
JOIN #WaitStats wd2 on
wd2.SampleTime =b.SampleTime
JOIN #WaitStats wd1 ON
wd1.wait_type=wd2.wait_type AND
wd2.SampleTime > wd1.SampleTime
CROSS APPLY (SELECT
cast((wd2.wait_time_ms-wd1.wait_time_ms)/1000. as numeric(10,1)) as [Wait Time (Seconds)],
cast((wd2.signal_wait_time_ms - wd1.signal_wait_time_ms)/1000. as numeric(10,1)) as [Signal Wait Time (Seconds)]) AS c
WHERE (wd2.waiting_tasks_count - wd1.waiting_tasks_count) > 0
and wd2.wait_time_ms-wd1.wait_time_ms > 0
ORDER BY [Wait Time (Seconds)] DESC;
-- ===========================================================================
-- ********** Begin Clean-Up **********
-- ===========================================================================
DROP TABLE #WaitStats
Run Code Online (Sandbox Code Playgroud)
正如我所说,这段代码需要 30 秒才能执行。因此,您点击“执行”,然后在第二个选项卡中运行运行缓慢的查询,然后返回第一个选项卡并等待结果。如果不清楚,请告诉我。
对于选项 2: 突然变慢的查询让我认为索引有问题。如果您的索引严重碎片化,则可能会影响执行计划,从而导致您遇到的问题。
假设您使用 SQL Management Studio 来运行查询,请在执行查询之前按“CTRL+M”。这将生成一个图形执行计划。如果您可以发布屏幕截图,它可能会给我们一些工作依据。这是假设您同意 StackExchange 用户看到您的表/索引名称。
根据您对一切的适应程度,您还可以获得 SQL Sentry Plan Explorer 的免费副本,它将允许您上传匿名执行计划,以便其他人可以深入查看它们。获取它和 SSMS 附加组件。当您按“CTRL+M”后执行查询时,您可以右键单击计划以在计划资源管理器中将其打开。
归档时间: |
|
查看次数: |
3682 次 |
最近记录: |