SQL Server 2008 R2에서 SQL Server 문이 간헐적으로 느려짐


13

고객 중 한 사람이 애플리케이션에서 일부 성능 문제를 겪고 있습니다. 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를 사용하고 있지만 서버는 우리가 아니라 클라이언트에 의해 설치 및 구성되었습니다.

누구 든지이 데이터를 좀 더 이해하도록 도울 수 있습니까? 누구든지 무슨 일이 일어나고 있는지 이해할 수 있습니까? 시도하고 알아 내기 위해 서버에서 할 수있는 일이 있습니까? 응용 프로그램 개발 팀에 문의해야합니까?

답변:


4

문제에 대한 자세한 설명 (실제로 가장 좋은 질문 중 하나)에 대해 감사합니다.

WRITELOG는 매우 일반적인 대기 유형이므로 걱정하지 마십시오. CPU 압력 및 CXPACKET을 나타내는 SOS_SCHEDULER_YIELD를 보면 누락 된 인덱스가 있어야하고 OLTP 시스템에 대한 쿼리에서 많은 데이터를 검색 할 수 있습니다. 누락 된 인덱스 DMV를보고 의심스러운 procs에있는 인덱스 (거의 몇 개 이상이 있는지)가 있는지 확인하십시오.

http://sqlfool.com/2009/04/a-look-at-missing-indexes/

http://troubleshootingsql.com/2009/12/30/how-to-find-out-the-missing-indexes-on-a-sql-server-2008-or-2005-instance-along-with-the- 색인 생성 명령 /

이것에 관한 sqlblog.com에서도 Jonathan Kehayias의 게시물을 찾으십시오.

또한 매개 변수 스니핑을 살펴보십시오.

http://sommarskog.se/query-plan-mysteries.html

http://pratchev.blogspot.com/2007/08/parameter-sniffing.html

그것은 당신의 요구에 대한 경쟁 답변이 아니라 좋은 출발점입니다. 자세한 내용이 필요하면 알려주십시오.


1

직원 중 한 명이 몇 가지 저장 프로 시저를 다시 쓴 후에도 비슷한 문제가 발생했습니다. where 절을 크게 변경 한 과도한 분기 및 동적 SQL 이 작성되는 것으로 나타났습니다.

예를 들어 (물론 단순화 됨) :

경우 모델 "X"이었다 찾았다 where 절 제품 코드는 특정 값을 동일.
경우] 모델 "Y"를 찾았습니다 WHERE 절 ProductType이 특정 값과 동일.

SQL Server는 저장 프로 시저가 처음 실행될 때 입력 매개 변수를 기반으로 쿼리 계획을 작성합니다. 따라서 쿼리 계획이 "ProductCode"equals를 사용하는 논리를 기반으로하고 "ProductType"이 같으면 쿼리 계획이 일치하지 않아서 전체 테이블 스캔이 발생할 가능성이 높습니다.

저장 프로 시저의 맨 위에 " WITH RECOMPILE "을 배치 할 수 있습니다 . 절차 작성 (Transact-SQL)

이것을 설명하는 가장 좋은 방법은 다음과 같습니다.

성으로 정렬 된 이름과 전화 번호 목록이 있다고 가정합니다. 성 (이름을 기반으로 한 쿼리 계획)을 사용하는 사람을 찾는 데 유용합니다. 이제 지역 번호 203에 모든 이름과 전화 번호가 필요하다고 가정합니다. 목록이 성으로 정렬 된 경우 모든 지역 번호 203 명 전체 목록을 얻는 유일한 방법은 맨 위에서 시작하여 각각을 순차적으로 읽는 것입니다. 모든 기록. (전체 테이블 스캔).


exec()기능을 사용 하면 관찰 된 동작을 설명 할 수 있습니다. 이 경우 sp_executesql일반적으로 사용 하면 동적 SQL 문 관련 문제가 해결됩니다.
ajeh

1

SSMS 및 앱에서 쿼리가 간헐적으로 빠르거나 느리게 실행되는 경우 통계 또는 매개 변수 스니핑 문제가있을 수 있습니다.

이 저장 프로 시저를 실행 한 다음 실행 계획을 검토하여 루트 연산자 (각 명령문의 가장 왼쪽에있는 녹색 노드)의 속성을 가져옵니다.

실행 계획의 예상 행 수와 실제 행 수는 몇 개입니까?

컴파일 된 매개 변수가 실제 쿼리 매개 변수와 일치합니까?

소수의 행만 리턴하는 매개 변수에 대해 실행 계획을 작성하고 다수의 행을 리턴하는 매개 변수를 사용하여 동일한 프로 시저를 실행하는 경우 SQL은 조회에 대해 잘못된 실행 계획을 사용할 수 있습니다.

실행 계획 선택 사항은 SQL 통계와 밀접하게 연결되어 있으므로 정기적으로 통계를 다시 작성하는 것이 좋습니다.

제공된 매개 변수에 따라 때때로 소량의 데이터 또는 대량의 데이터를 리턴하는 스토어드 프로 시저가있는 경우 매개 변수 스니핑 문제점이있을 수 있습니다.

통계를 다시 작성해도 문제가 해결되지 않으면 저장 프로 시저에서 가장 비싼 명령문을 실행할 수 있습니다. OPTION (RECOMPILE)


0

오래 실행되는 쿼리를 식별했으면 캐시에서 이러한 프로 시저에 대한 실행 계획을 가져 와서 문제를 확인할 수 있는지 확인할 수 있습니다. 종종 데이터 유형의 암시 적 또는 런타임 변환이 있습니다. 또한 많은 데이터를 제거하거나 삽입하는 경우 통계도 업데이트하는 것이 좋습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.