LATCH_EX는 리소스를 기다립니다. METADATA_SEQUENCE_GENERATOR


11

재고 보고서를 생성하는 프로세스가 있습니다. 클라이언트 쪽에서 프로세스는 구성 가능한 수의 작업자 스레드로 분할되어 여러 저장소 (잠재적으로 수천 개, 일반적으로 수십 개) 중 하나에 해당하는 보고서에 대한 데이터 청크를 작성합니다. 각 작업자 스레드는 저장 프로 시저를 실행하는 웹 서비스를 호출합니다.

각 청크를 처리하기위한 데이터베이스 프로세스는 #Temporary 테이블에 많은 데이터를 수집합니다. 각 처리 청크의 끝에서 데이터는 tempdb의 영구 테이블에 기록됩니다. 마지막으로 프로세스가 끝날 때 클라이언트 측의 하나의 스레드가 영구 tempdb 테이블의 모든 데이터를 요청합니다.

이 보고서를 실행하는 사용자가 많을수록 속도가 느려집니다. 데이터베이스의 활동을 분석했습니다. 한 시점에서 프로세스의 한 지점에서 35 개의 개별 요청이 모두 차단되는 것을 보았습니다. 이러한 SPID는 모두 LATCH_EX리소스에서 50ms 대기 유형 입니다 METADATA_SEQUENCE_GENERATOR (00000010E13CA1A8). 한 SPID에이 리소스가 있으며 다른 SPID는 모두 차단하고 있습니다. 웹 검색 에서이 대기 리소스에 대한 내용을 찾지 못했습니다.

우리가 사용하는 tempdb의 테이블에는 IDENTITY(1,1)열이 있습니다. 이 SPID가 IDENTITY 열을 기다리고 있습니까? 차단을 줄이거 나 없애기 위해 어떤 방법을 사용할 수 있습니까?

서버는 클러스터의 일부입니다. 서버가 64 비트 Windows 2008 R2 Enterprise에서 64 비트 SQL Server 2012 Standard Edition SP1을 실행하고 있습니다. 서버에는 64GB RAM과 48 개의 프로세서가 있지만 표준 버전이므로 데이터베이스는 16 개만 사용할 수 있습니다.

(이 모든 데이터를 보유하기 위해 tempdb에 영구 테이블을 사용하는 디자인에 감격하지는 않습니다.이 기술을 변경하는 것은 흥미로운 기술적, 정치적 도전이 될 수 있지만 제안 사항은 열려 있습니다.)

2013 년 4 월 23 일 업데이트

Microsoft와 함께 지원 사례를 개설했습니다. 자세한 내용은이 질문을 계속 업데이트하겠습니다.

2013 년 5 월 10 일 업데이트

SQL Server 지원 엔지니어는 대기가 IDENTITY 열에 의해 발생한다는 데 동의했습니다. IDENTITY를 제거하면 대기 시간이 제거되었습니다. SQL 2008 R2에서이 문제를 복제 할 수 없었습니다. SQL 2012에서만 발생했습니다.


프로세스가 본질적으로 #Temporary 테이블에서 영구 테이블로 데이터를 복사합니까, 아니면 해당 단계에서 추가 변환 논리가 발생합니까?
Jon Seigel

대기중인 단계에서 단일 상점의 재고 레코드를 변환없이 영구 테이블에 복사합니다. 우리는 항상 영구 테이블 내부에서 작업 할 수 있지만 프로그래머는 #Temporary 테이블을 유지 영역으로 사용하여 데이터의 빈번한 업데이트가 PAGE 잠금으로 변환되지 않도록 선택했다고 생각합니다.
Paul Williams

답변:


4

문제를 ID 값 생성으로 분리 할 수 ​​있다고 가정하면 (해당 열을 테스트로 제거하십시오) 권장하는 것은 다음과 같습니다.

  1. IDENTITY최종 테이블의 열에서 속성을 제거하십시오 .
  2. 각 #Temporary 테이블에서 ID 값을 생성하십시오.
  3. 최종 테이블을로드 할 때 특정 상점의 숫자 ID를 2 단계의 ID 값과 결합하십시오.

따라서 상점 ID 3과 4가 있으면 다음과 같이 최종 id 값으로 끝납니다.

3000000001
3000000002
3000000003
...
4000000001
4000000002
...

아니면 그와 비슷한 것. 당신은 아이디어를 얻습니다.

따라서 IDENTITY최종 결과에서 고유성을 유지하면서 생성시 직렬화 할 필요가 없습니다 .

또는 프로세스 작동 방식에 따라 최종 계산 된 id 값을 #Temporary 테이블에 삽입하십시오. 그런 다음 UNION ALL함께 보기를 만들어 데이터를 전혀 복사 할 필요가 없습니다.


답변 주셔서 감사합니다. 그것이 문제라면 동의합니다. 제조 된 키를 사용하거나 전혀 키를 사용하지 않으면 문제가 해결 될 수 있습니다. 이 문제와 관련하여 Microsoft에 사례를 개설했습니다. 결과를 여기에 게시하고 문제에 동의하면 답변을 수락하겠습니다.
Paul Williams

@Paul : 알려주세요; 그냥 궁금 해서요 당신처럼, 나는이 래치에 대해 웹에서 아무것도 찾을 수 없었지만 그것이 정체성 / 시퀀스 직렬화라는 것이 합리적입니다. 병목 현상인지 여부는 말하기가 어렵지만 30 개 이상의 스레드가 값을 놓고 경쟁하기 때문에 가능성이 높습니다. 또한 각 #Temporary 테이블을 병렬 대신에 직렬로 복사하여 도움이되는지 확인할 수도 있습니다.
Jon Seigel

2
SQL Server 엔지니어는 아마도 IDENTITY열 이라고 동의했습니다 . 우리는 이미 넓은 클러스터 인덱스에서 그것을 제거하고 열을 완전히 제거했습니다. 필요하지 않았습니다. 이후에 LATCH_EX 대기 시간이 사라졌습니다. SQL 2008 R2에서 대기를 복제 할 수 없습니다. 이 문제는 SQL 서버 2012에 무슨 일이 있었
폴 윌리엄스

@Paul : 팔로우 해 주셔서 감사합니다. 매우 흥미로운. IDENTITY값 을 생성하는 코드가 2012 년에 새로 도입 된 새로운 시퀀스 생성 항목을 사용하도록 다시 작성 되었다고 생각합니다 . <2012 년에는 다른 래치 유형이 표시 될 수 있지만 성능 문제가없는 경우에는 다른 래치 유형이 표시 될 수 있습니다. 코드의 회귀 어쨌든 IDENTITY열을 제거하는 것이 가장 안전합니다.
Jon Seigel

ID 대신 'SEQUENCE'(SQL 2012의 새로운 기능)를 사용하려고 할 수 있습니다.
Bogdan Maxim

7

(2019 년 2 월 업데이트)

이것은 오래된 게시물입니다. 마지막으로 이것이 실제로 발생한다는 사실은 실제로 결함이라고 Microsoft에 확신 시켰습니다.

업데이트 : MS에서 결함을 확인하고 버그 # 12628722를 할당했습니다.

Sql Server 2005에서 Sql Server 2017로 업그레이드 한 후 2018 년 11 월에이 게시물을 보았을 때이 게시물을 보았습니다. 대량 삽입에 10 초가 걸리던 330 만 개의 행 테이블이 갑자기 10을 가져 오기 시작했습니다. Identity열이있는 테이블에서 분 .

이 뒤에 두 가지 문제가 있음이 밝혀졌습니다.

  1. Microsoft는 Sql Server 2014의 동작을 변경하여 대량 삽입이 병렬로 실행되도록했습니다. 이전 버전에서는 대량 삽입에 직렬화 된 계획이 제공되었습니다.
  2. 32 코어 박스에서 병렬로 실행되면 엔진은 실제로 작업을 수행하는 것보다 코어를 서로 잠그는 데 더 많은 시간을 보냈습니다.

4 주가 걸렸지 만 휴일이 끝나 자마자 나는 산타에게 뒤늦은 선물을 받았습니다.

이 문제가 해결 될 때까지 몇 가지 가능한 해결 방법이 있습니다.

  1. 사용 Option (MaxDop 1)쿼리는 직렬화 된 계획에 대량 삽입 다시 전원을 켭니다.
  2. (예를 캐스팅하여 ID 열 마스크 Select Cast(MyIdentityColumn As Integer) As MyIdentityColumn)
    • 이렇게하면 사용시 ID 속성이 복사되지 않습니다 SELECT...INTO
  3. 위에서 설명한대로 식별 컬럼을 제거하십시오.
  4. 직렬화 된 계획을 다시 설정하려면 데이터베이스 호환성 모드를 Sql Server 2012 이하로 변경하십시오.

업데이트 : MS가 구현할 수정 사항은 이러한 종류의 삽입물을 Serialized 계획 을 사용하여 다시 되 돌리는 것 입니다. 이것은 Sql Server 2017 CU14 용으로 계획되었습니다 ( Sql Server의 다른 버전에 대한 뉴스는 없습니다. 죄송합니다). 구현되면 서버 수준에서 또는를 통해 추적 플래그 9492를 켜야 합니다DBCC TraceOn .

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