SQL Server 성능 급격한 저하


13

늦게 예측할 수없는 SQL Server 2005가 있는데 그 이유에 대해 머리를 긁고 있습니다. 초 단위로 실행 된 쿼리는 계획을 변경하고 몇 분이 소요됩니다 (전체 테이블 스캔 또는 인덱스 스풀에서 시간 소요). 이제 첫 번째로 가장 확실한 것은 통계가 더 이상 사용되지 않아 옵티마이 저가 혼란스러워하지만 이것이 사실이 아니라고 확신합니다. 첫째로 기본 데이터가 크게 변경되지 않기 때문에 (예 : 1 년 데이터 위에 하루 데이터 추가) 자동 생성 통계 및 자동 업데이트 통계가 모두 참이므로 두 번째로 이미 테이블에 있습니다. 그러나 최적화 되어 혼란스러워지고; Tuning Advisor에서 SQL을 실행하면 CREATE STATISTICS수정하는 것처럼 보이는 여러 열로 된 많은 문장이 나옵니다 (SQL의 다음 비트가 잘못 동작 할 때까지).

근본 원인에 접근하기 위해 사용할 수있는 전략에 대한 아이디어가 있습니까? 왜 "정상적인"통계가 충분하지 않은가?

답변:


8

최고 대기 시간이 SOS_SCHEDULER_YIELD 인 경우 CPU에 약간의 압력이있는 것으로 나타납니다. 그러나 이것은 디자인이 더 이상 쿼리에 충분하지 않은 것과 같은 다른 결과 일 수 있습니다. 하루 동안의 데이터 만 추가한다고 말했지만 팁을 줄 수 있습니다.

쿼리는 어떻게 발행됩니까? 동적 SQL입니까? 저장 프로 시저를 사용하고 있습니까? sp_executesql을 사용하고 있습니까? 매개 변수 스니핑이 발생할 수 있습니까? DB 디자인은 어떻게 생겼습니까? PK와 FK 관계는 무엇입니까?

좋은 계획의 예가 있습니까? 적절한 계획을 결정할 수있는 경우 계획 지침을 사용하여 쿼리가 특정 방식으로 실행되도록 할 수 있습니다.

좋은 계획의 예가 나빠질 수 있습니까?

마지막으로 Adam Machanic 의 sp_whoIsActive ( http://whoisactive.com/ ) 복사본을 가져 와서 실행중인 쿼리에 대한 자세한 정보를 확인하십시오. sp_whoIsActive의 출력을 캡처하려면 http://www.littlekendra.com/2011/02/01/whoisactive/ 로 이동하십시오 .


내가 꽤 끔찍 스키마 또는 SQL, 매개 변수화 된 쿼리 (예를 들어, 많은 여부를 제어 할 수 없습니다, 타사 응용 프로그램의 where col=(cast @var...))와 @var수 있습니다 '%'. 나는 단지 1-2 주 전에 그것을 물려 받았으며 교체 될 때까지 기본적으로 작동해야합니다. 링크 주셔서 감사합니다, 나는 그것을 소용돌이를 줄 것이다.
Gaius

이후 다음으로 가장 큰 대기 SOS_SCHEDULER_YIELD이었다 CXPACKET하고 sp_configure "max degree of parallelism", 1있는 것 같습니다 - 지금 - 머리에 두 문제를 두드렸다. 감사!
Gaius

sp_whoIsActive에 링크 +1
Jeff

8

에서 MSDN :

" 오름차순 또는 내림차순 키 열에서 삽입 작업이 발생 함 IDENTITY 또는 실시간 타임 스탬프 열과 같이 오름차순 또는 내림차순 키 열에 대한 통계는 쿼리 최적화 프로그램이 수행하는 것보다 더 자주 통계를 업데이트해야합니다. 삽입 작업은 오름차순 또는 내림차순 열에 새 값을 추가합니다 추가 된 행 수가 너무 작아서 통계 업데이트를 트리거 할 수없는 경우 통계가 최신 상태가 아니고 쿼리가 가장 최근에 추가 된 행에서 선택하는 경우 현재 통계에는 이러한 새 값에 대한 카디널리티 추정치가 없습니다. 카디널리티 추정이 부정확하고 쿼리 성능이 느려집니다.

예를 들어, 가장 최근 판매 주문 날짜에서 선택하는 쿼리는 통계가 최신 판매 주문 날짜에 대한 카디널리티 추정치를 포함하도록 업데이트되지 않은 경우 카디널리티 추정치가 부정확합니다.

유지 관리 작업 후 테이블 자르기 또는 대량의 행을 대량으로 삽입하는 등의 데이터 배포를 변경하는 유지 관리 절차를 수행 한 후 통계 업데이트를 고려하십시오. 이렇게하면 쿼리가 자동 통계 업데이트를 기다리는 동안 쿼리 처리가 지연되는 것을 피할 수 있습니다. "

시스템에서 때때로 "EXEC sp_updatestats"를 사용하거나 (일정 예약 됨) 모든 객체에서 STATS_DATE 함수를 사용하여 통계가 실제로 마지막으로 업데이트 된 시간을 확인한 후 이후로 너무 많은 시간이 있으면 UPDATE를 사용하십시오. 해당 특정 개체에 대한 통계. 필자의 경험에 따르면 자동 통계를 사용하더라도 자동 업데이트를 트리거하지 않은 삽입 작업으로 인해 때때로 통계를 업데이트해야합니다.

내 개인 코드를 추가하려면 (통계 업데이트에 대한 동적 설명을 작성하는 주간 작업에서 사용) :

select distinct
        'update statistics [' + stats.SchemaName + '].[' + stats.TableName + ']'
            + case when stats.RowCnt > 50000 then ' with sample 30 percent;'
            else 
                ';' end
        as UpdateStatement
    from (
        select
            ss.name SchemaName,
            so.name TableName,
            so.id ObjectId,
            st.name AS StatsName, 
            STATS_DATE(st.object_id, st.stats_id) AS LastStatisticsUpdateDate
            , si.RowModCtr
            , (select case si2.RowCnt when 0 then 1 else si2.RowCnt end from sysindexes si2 where si2.id = si.id and si2.indid in (0,1)) RowCnt
        from sys.stats st
            join sysindexes si on st.object_id = si.id and st.stats_id = si.indid
            join sysobjects so on so.id = si.id and so.xtype = 'U' --user table
            join sys.schemas ss on ss.schema_id = so.uid
    ) stats
    where cast(stats.RowModCtr as float)/cast(stats.RowCnt as FLOAT)*100 >= 10 --more than 10% of the rows have changed
    or ( --update statistics that were not updated for more than 3 months (and rows no > 0)
        datediff(month, stats.LastStatisticsUpdateDate, getdate()) >= 3
        and stats.RowCnt > 0
    )

여기에 3 개월 이상 통계가 업데이트되지 않았거나 마지막 통계 업데이트 이후 행의 10 % 이상이 변경된 모든 객체를 얻습니다.


흠, 내 최고 대기 이벤트 SOS_SCHEDULER_YIELD이지만 계획이 잘못 되었거나이 (6 세, 2 프로세서, 4G RAM) 상자가 실제로 과부하되어 있는지 지금 알 수 없습니다. 티핑 포인트를 넘어 섰습니다.
Gaius

해당 쿼리를 실행하여 UPDATE 문을 만들고 수동으로 실행하는 대신 해당 select 문을 기반으로하는 커서를 사용하여 sp_executesql에 대한 호출을 사용하여 실행중인 결과를 순환 할 수 있습니다 (예 : 부분으로) 하룻밤 (또는 다른 조용한 기간) 유지 보수 계획).
David Spillett

@David : 이것은 주간 작업에서하는 일입니다 :). Gaius가 내가 사용하는 출력을 볼 수 있도록 다르게 포맷했습니다. 초기 스크립트는 너무 추하고 길었습니다. 포맷팅에 도움을 주셔서 감사합니다! 여기에서 코드를 멋지게 보이게 만드는 방법을 모르기 때문에 서식 자습서로 나를 보낼 수 있습니까? 감사!
Marian

"답변 편집"화면에는 "포맷 도움말"링크가 있으며 기본 질문 페이지의 첫 번째 답 상자 바로 위 아이콘으로 이러한 사이트에서 지원되는 마크 다운 구문이 나열되어 있습니다.
David Spillett

3
자동 업데이트 통계는 실제로 10 %가 아니라 20 % + 500 행에서 트리거됩니다.
mrdenny

3

내 생각에 하나 이상의 테이블이 커져서 현재 통계를 오래된 것으로 표시하는 데 필요한 20 %의 변경 사항에 도달하지 않아 자동 업데이트 통계가 시작되고 충분한 업데이트 (또는 삽입물이 있음) ) 통계를 업데이트하면 많은 도움이 될 것입니다. SQL 2000에서 SQL 2008로 업그레이드 한 후 특정 환경에서 최근에 동일한 것을 발견했습니다.

위의 답변에 언급 된 다른 사이트 외에도 다음 온라인 리소스를 확인하는 것이 좋습니다.

1) Red-Gate에는 Holger Schmeling의 "SQL Server Statistics"를 포함하여 무료로 다운로드 할 수있는 다양한 전자 책이 있으며 여기에는 다음과 같은 인용문이 있습니다.

http://www.red-gate.com/our-company/about/book-store/

"링크 된 통계를 무효화하기 위해 열 데이터의 20 % 이상이 500 행 이상인 테이블을 변경해야했습니다."

2) SQL Sentry에는 쿼리의 지정된 테이블에 대한 실제 행 수와 비교할 때 너무 많거나 너무 적은 행의 추정치와 같은 SQL 계획 내의 문제를 추적하는 데 도움이되는 무료 계획 탐색기 도구가 있습니다. SSMS에서 실제 실행 계획을 저장 한 다음 계획 탐색기를 사용하여 계획의 다른 부분을 살펴보십시오. SSMS에서 그래픽 실행 계획을 사용하여 정보를 사용할 수있는 것은 아니지만 SQL Sentry의 도구를 사용하면 훨씬 쉽게 볼 수 있습니다.

http://www.sqlsentry.com/plan-explorer/sql-server-query-view.asp

3) STATS_DATE () 사용에 가장 관심이있는 쿼리의 테이블에 대한 통계 업데이트 날짜를 직접 확인하십시오. 다음 토론에서 찾은 쿼리를 사용하여 가장 오래된 통계를 얻는 빠른 쿼리를 찾을 수 있습니다.

http://blog.sqlauthority.com/2010/01/25/sql-server-find-statistics-update-date-update-statistics/

이게 도움이 되길 바란다!

Red-Gate의 책을 특히 좋아할 것입니다!

-제프


감사합니다 나는 주로이 시스템을 물려받은 Oracle DBA입니다. (2005 년 이후 내가 본 것으로부터 SQL Server에 대해 전혀 편견이 없습니다. 그것은 매우 유능한 플랫폼입니다. .
Gaius
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.