고객 중 한 사람이 애플리케이션에서 일부 성능 문제를 겪고 있습니다. SQL Server 데이터베이스의 데이터를 사용하고 업데이트하는 .NET 3.5 웹앱입니다. 현재 프로덕션 환경은 프런트 엔드 인 Windows 2008 R2 시스템과 백 엔드의 SQL Server 2008 R2 클러스터로 구성되어 있습니다. 우리의 앱은 COM +와 MSDTC를 사용하여 데이터베이스에 연결합니다.
현재 상황은 다음과 같습니다. 최종 사용자는 때때로 응용 프로그램의 속도 저하에 대해 불평합니다. 일부 페이지를로드하는 데 예상보다 시간이 더 걸립니다. 무슨 일이 일어나고 있는지 알아 내려고 노력하면서 데이터베이스 쪽에서 성능 저하의 원인이 될 수있는 이상한 동작을 발견했습니다. 때로는 예상되는 것을 실행하는 데 많은 시간이 걸리는 SQL 문이 있음을 알았습니다. 장기 실행 쿼리를 식별하기 위해 프로파일 러 추적 (TSQL_Duration 템플릿 사용)을 사용하여 이러한 명령문 중 일부 (주로 애플리케이션의 일부 스토어드 프로 시저 호출)를 식별 할 수있었습니다.
문제는 SQL Management Studio의 데이터베이스에서 직접 이러한 저장 프로 시저를 실행할 때 시간이 오래 걸리고 (약 7/8 초), 다른 경우에는 빠르다 (1 초 미만)라는 것입니다. SQL 응용 프로그램 (4 코어, 32GB)을 다른 응용 프로그램에서 사용하고 있지 않으므로이 문제가 발생하는 이유를 모르겠으며 견딜 수 없습니다.이 쿼리를 실행하는 데 오래 걸리지 않아야합니다.
DBA 또는 SQL Server 전문가가 아니기 때문에 문제를 이해하는 데 도움이되는 몇 가지 사항을 살펴 보았습니다. 다음은 문제를 해결하기 위해 취한 단계와 지금까지 찾은 내용입니다.
- 응용 프로그램이 호출 한 모든 TSQL 코드는 스토어드 프로 시저로 작성됩니다.
- SQL Server 프로파일 러에서 오래 실행되는 쿼리 중 일부를 식별했지만 Management Studio에서이 쿼리를 실행하면 실행하는 데 시간이 오래 걸리거나 (4-10 초), 빠르게 실행됩니다 (1 초 미만). 매개 변수에 전달 된 동일한 데이터로 정확히 동일한 쿼리를 실행하고 있습니다. 이러한 쿼리는 주로 select 문이있는 저장 프로 시저입니다.
- 대기 및 대기열 통계를보고 일부 리소스에서 대기중인 프로세스가 있는지 알아 내려고 시도했습니다. 다음 쿼리를 실행했습니다.
WITH Waits AS
(SELECT
wait_type,
wait_time_ms / 1000.0 AS WaitS,
(wait_time_ms - signal_wait_time_ms) / 1000.0 AS ResourceS,
signal_wait_time_ms / 1000.0 AS SignalS,
waiting_tasks_count AS WaitCount,
100.0 * wait_time_ms / SUM (wait_time_ms) OVER() AS Percentage,
ROW_NUMBER() OVER(ORDER BY wait_time_ms DESC) AS RowNum
FROM sys.dm_os_wait_stats
WHERE wait_type NOT IN (
'CLR_SEMAPHORE', 'LAZYWRITER_SLEEP', 'RESOURCE_QUEUE', 'SLEEP_TASK',
'SLEEP_SYSTEMTASK', 'SQLTRACE_BUFFER_FLUSH', 'WAITFOR', 'LOGMGR_QUEUE',
'CHECKPOINT_QUEUE', 'REQUEST_FOR_DEADLOCK_SEARCH', 'XE_TIMER_EVENT', 'BROKER_TO_FLUSH',
'BROKER_TASK_STOP', 'CLR_MANUAL_EVENT', 'CLR_AUTO_EVENT', 'DISPATCHER_QUEUE_SEMAPHORE',
'FT_IFTS_SCHEDULER_IDLE_WAIT', 'XE_DISPATCHER_WAIT', 'XE_DISPATCHER_JOIN', 'BROKER_EVENTHANDLER',
'TRACEWRITE', 'FT_IFTSHC_MUTEX', 'SQLTRACE_INCREMENTAL_FLUSH_SLEEP',
'BROKER_RECEIVE_WAITFOR', 'ONDEMAND_TASK_QUEUE', 'DBMIRROR_EVENTS_QUEUE',
'DBMIRRORING_CMD', 'BROKER_TRANSMITTER', 'SQLTRACE_WAIT_ENTRIES',
'SLEEP_BPOOL_FLUSH', 'SQLTRACE_LOCK')
)
SELECT
W1.wait_type AS WaitType,
CAST (W1.WaitS AS DECIMAL(14, 2)) AS Wait_S,
CAST (W1.ResourceS AS DECIMAL(14, 2)) AS Resource_S,
CAST (W1.SignalS AS DECIMAL(14, 2)) AS Signal_S,
W1.WaitCount AS WaitCount,
CAST (W1.Percentage AS DECIMAL(4, 2)) AS Percentage,
CAST ((W1.WaitS / W1.WaitCount) AS DECIMAL (14, 4)) AS AvgWait_S,
CAST ((W1.ResourceS / W1.WaitCount) AS DECIMAL (14, 4)) AS AvgRes_S,
CAST ((W1.SignalS / W1.WaitCount) AS DECIMAL (14, 4)) AS AvgSig_S
FROM Waits AS W1
INNER JOIN Waits AS W2 ON W2.RowNum <= W1.RowNum
GROUP BY W1.RowNum, W1.wait_type, W1.WaitS, W1.ResourceS, W1.SignalS, W1.WaitCount, W1.Percentage
HAVING SUM (W2.Percentage) - W1.Percentage < 95; -- percentage threshold
GO
내가 찾은 것은 다음과 같습니다.
- DBCC SQLPERF (약 1 시간 또는 2 시간 후)를 사용하여 통계를 재설정 한 후 가장 많이 사용하는 대기 유형은 SOS_SCHEDULER_YIELD 및 WRITELOG입니다.
- 시간이 지남에 따라 (약 1 일 실행 후) 데이터베이스에서 가장 많이 발생하는 대기 유형은 CXPACKET (67 %) 및 OLEDB (17 %)이지만 각 평균 대기 시간은 길지 않습니다. 또한 SQL 프로필러에서 식별 된 장기 실행 문은 둘 이상의 결과 집합 (종종 3)을 반환하는 저장 프로 시저에 대한 호출이라는 것을 알았습니다. 여기에 평 행성 문제가있을 수 있습니까? 이것이 문제의 원인인지 식별 할 수있는 방법이 있습니까?
- 연결된 서버와 같은 OLEDB 리소스에 대한 호출로 인해 OLEDB 대기가 발생할 수있는 곳을 읽었습니다. 인덱싱 서비스 시스템 (MSIDXS)에 연결하기위한 연결된 서버가 있지만 장기 실행으로 식별 된 명령문은 해당 연결된 서버를 사용하지 않습니다.
- 내가 가지고있는 평균 대기 시간은 LCK_M_X 유형 대기 (평균 약 1.5 초)에 대한 것이지만 이러한 대기 유형은 다른 유형과 비교하여 자주 발생하지 않습니다 (예 : 64 LCK_M_X 대기 대 10,823 CXPACKET 대기 시간과 같은 기간) ).
- 내가 주목 한 것은 MSDTC 서비스가 클러스터되지 않았다는 것입니다. SQL Server 서비스는 클러스터되었지만 MSDTC는 아닙니다. 이로 인해 성능이 저하 될 수 있습니까? 앱이 DCOM (Enterprise Services)을 사용하여 데이터베이스에 액세스하기 때문에 MSDTC를 사용하고 있지만 서버는 우리가 아니라 클라이언트에 의해 설치 및 구성되었습니다.
누구 든지이 데이터를 좀 더 이해하도록 도울 수 있습니까? 누구든지 무슨 일이 일어나고 있는지 이해할 수 있습니까? 시도하고 알아 내기 위해 서버에서 할 수있는 일이 있습니까? 응용 프로그램 개발 팀에 문의해야합니까?
exec()
기능을 사용 하면 관찰 된 동작을 설명 할 수 있습니다. 이 경우sp_executesql
일반적으로 사용 하면 동적 SQL 문 관련 문제가 해결됩니다.