KB3067257 - 수정: 2014년 SQL Server 클러스터형 columnstore 인덱스의 쿼리 결과 부분

적용 대상
SQL Server 2014 Developer - duplicate (do not use) SQL Server 2014 Enterprise - duplicate (do not use) SQL Server 2014 Standard - duplicate (do not use)

이 문서에서는 Microsoft SQL Server 2014에서 클러스터형 columnstore 인덱스를 쿼리하는 동안 발생하는 문제에 대해 설명합니다. 이 문서에서는 이 문제에 대한 해결 방법을 제공합니다.

요약​​

Microsoft SQL Server 2014에서 클러스터형 columnstore 인덱스를 검사하는 쿼리를 사용하는 경우 드문 조건에서 부분 쿼리 결과를 받을 수 있습니다.

이 문제는 다음 작업을 실행할 때 발생합니다.

1단계

Transact-SQL 문 [INSERT 또는 BULK-INSERT]은 클러스터형 columnstore 인덱스가 있는 테이블에 데이터를 삽입합니다. 이 작업 중에는 다음 조건이 적용됩니다.

  • Transact-SQL 문이 행 그룹 임계값에 도달하면 세그먼트 S1이 있는 행 그룹 R1을 닫습니다.
  • S1 세그먼트는 로컬 사전 D1을 가리킵니다.
  • 문은 계속해서 새 행 그룹 R2에 행을 삽입합니다.
  • 행 그룹 R1이 닫혀 있으면 로컬 사전 D1도 닫을 필요가 없습니다. 사전 D1에 사용 가능한 공간이 있는 경우 열어 두고 새 행 그룹 R2에 다시 사용할 수 있습니다.

2단계

Transact-SQL 문이 새 행 그룹 R2를 닫기 전에 비정상적으로 종료되거나 취소된 경우 다음 조건이 적용됩니다.

  • Columnstore 메타데이터 변경은 외부 트랜잭션과 독립적으로 커밋되는 하위 트랜잭션에서 발생합니다.
  • 이 시점에서 행 그룹 R1은 시스템 테이블에 "생성 중" 또는 INVISIBLE 상태로 유지되고 세그먼트 S1은 사전 D1을 참조합니다.
  • 시스템 테이블에 사전 D1에 대해 만든 행이 없습니다. Transact-SQL 문에는 기존 행을 닫을 기회가 없기 때문입니다. 따라서 기존 행은 유지됩니다.

3단계

일반적인 상황에서 Transact-SQL 문이 종료된 후 튜플 이동기 백그라운드 작업이 시작되면 백그라운드 작업은 보이지 않는 행 그룹 R1 및 세그먼트 S1을 제거합니다. 새 Transact-SQL 문이 지금 시작되고 새 로컬 사전이 필요한 새 세그먼트 S3이 있는 행 그룹 R3을 만드는 경우 사전 D1의 내부 ID를 다시 사용할 수 없습니다. columnstore의 메모리 내 상태가 사용되는 사전 ID를 추적하기 때문입니다. 따라서 세그먼트 S3은 새 사전 D2를 참조합니다.

참고 이 단계의 조건은 일반적인 조건입니다. 따라서 손상이 발생하지 않습니다.

4단계

튜플 이동기 작업이 적용되기 전에 SQL Server 사전 D1의 메모리 내 상태가 손실되고 3단계에 설명된 대로 수행되면 이 문서에 설명된 문제가 발생합니다.

노트

  • 이 이벤트는 다음과 같은 이유로 발생합니다.

    • SQL Server 메모리 오버로드가 발생하며 D1 사전의 메모리 내 콘텐츠가 메모리에서 제거됩니다.
    • SQL Server instance 다시 시작됩니다.
    • 클러스터형 columnstore 인덱스가 포함된 데이터베이스가 오프라인 상태가 된 후 다시 온라인 상태가 됩니다.
  • 이러한 이벤트 중 하나가 발생하고 메모리 내 구조를 다시 로드할 SQL Server 후에는 사전 D1 및 내부 ID가 있었다는 레코드가 없습니다. Transact-SQL 문이 종료되거나 연결되었을 때 사전 D1이 시스템 테이블에 유지되지 않았기 때문입니다.

  • 이 시점에서 튜플 이동기 백그라운드 작업이 시작되면 3단계에 설명된 조건이 적용되므로 오류가 발생하지 않습니다.

  • 튜플 이동기 백그라운드 작업이 시작되기 전에 새 행 그룹 R3을 만든 경우(이전 글머리 기호 항목당) SQL Server 새 사전 D1에 동일한 내부 ID를 할당하고 행 그룹 R3의 세그먼트 S3에 대한 사전 D1을 참조합니다.

  • 이전 작업 후에 튜플 이동기 백그라운드 작업이 시작되면 보이지 않는 행 그룹 R1 및 해당 세그먼트 S1을 새 사전 D1과 함께 삭제합니다. 이는 튜플 이동기가 새 사전 D1 및 S1 참조가 동일한 원래 사전 D1을 고려하기 때문에 발생합니다.

    참고 이 조건이 발생하면 행 그룹 R3의 내용을 쿼리할 수 없습니다.

해결 방법

이 문제는 SQL Server 대한 다음 누적 업데이트에서 처음 해결되었습니다.

SQL Server 2014 SP1의 누적 업데이트 1
        
         SQL Server 2014의 누적 업데이트 8
이 문제에 대한 수정 사항은 다음과 같은 GDR(일반 배포 릴리스) 업데이트에도 포함되어 있습니다.

SQL Server 2014 QFE용 보안 업데이트  
이 업데이트에는 누적 업데이트 8, 이 중요한 수정 사항 및 필요한 MS15-058 보안 업데이트가 포함됩니다.

SQL Server 2014 GDR용 보안 업데이트  
이 업데이트에는 MS15-058을 통한 이 중요한 수정 사항 및 누적 보안 수정이 포함됩니다.

SQL Server 2014 서비스 팩 1 GDR에 대한 비보안 업데이트  
이 업데이트에는 이 중요한 수정 사항만 포함됩니다.

SQL Server 대한 누적 업데이트 정보

SQL Server 대한 각각의 새로운 누적 업데이트에는 이전 누적 업데이트에 포함된 모든 핫픽스 및 모든 보안 수정 사항이 포함됩니다. SQL Server 대한 최신 누적 업데이트를 참조하세요.

      

추가 정보

오류 메시지 현재 영향을 받는 데이터베이스에서 이 수정을 적용한 후 DBCC CHECKDB를 실행하는 경우 다음과 같은 오류 메시지가 표시됩니다.

참고

Msg 5289, 수준 16, 상태 1, 줄 1
테이블 't'의 클러스터형 columnstore 인덱스 'cci'에는 사전의 데이터 값과 일치하지 않는 하나 이상의 데이터 값이 있습니다. 백업에서 데이터를 복원합니다.

현재 영향을 받는 데이터베이스에서 이 수정을 적용한 후 영향을 받는 테이블을 검사하는 쿼리를 실행하면 다음과 같은 오류 메시지가 표시됩니다.

참고

Msg 5288, 수준 16, 상태 1, 줄 1
Columnstore 인덱스는 사전의 데이터 값과 일치하지 않는 하나 이상의 데이터 값이 있습니다. 자세한 내용은 DBCC CHECKDB를 실행하세요.

이러한 오류가 발생하면 영향을 받지 않는 열/행 그룹의 데이터를 대량으로 내보낸 다음 클러스터형 columnstore 인덱스를 삭제하거나 만든 후 데이터를 다시 로드하여 부패하지 않은 데이터를 저장할 수 있습니다. 추적 플래그 10207을 사용하도록 설정하여 5288 오류를 표시하지 않고 손상된 행 그룹을 건너뛰는 이전 동작으로 되돌리기 합니다.

참고 세그먼트 S3이 있는 이 행 그룹 R3에 대해 오류 메시지 5288 및 5289가 생성됩니다. 추적 플래그 10207은 누락된 사전 D1의 영향을 받지 않는 행 그룹 R3의 세그먼트를 추출하는 데 사용됩니다.

영향을 받는 데이터베이스에 대한 쿼리 columnstore 인덱스가 포함된 데이터베이스가 이미 이 문제의 영향을 받고 있는지 확인하려면 다음 쿼리를 실행합니다.

select  
       object_name(i.object_id) as table_name, 
       i.name as index_name, 
       p.partition_number, 
       count(distinct s.segment_id) as damaged_rowgroups 
from 
       sys.indexes i 
       join sys.partitions p on p.object_id = i.object_id and p.index_id = i.index_id 
       join sys.column_store_row_groups g on g.object_id = i.object_id and g.index_id = i.index_id and g.partition_number = p.partition_number 
       join sys.column_store_segments s on s.partition_id = p.partition_id and s.segment_id = g.row_group_id 
where  
       i.type in (5, 6) 
       and s.secondary_dictionary_id <> -1  
       and g.state_description = 'COMPRESSED' 
       and s.secondary_dictionary_id not in 
       ( 
              select dictionary_id from sys.column_store_dictionaries d 
              where d.hobt_id = p.hobt_id and d.column_id = s.column_id 
       ) 
group by  
       object_name(i.object_id), 
       i.name, 
       p.partition_number 

노트

  • SQL Server 실행 중인 서버의 columnstore 인덱스가 포함된 모든 데이터베이스에 대해 이 쿼리를 실행해야 합니다. 빈 결과 집합은 데이터베이스가 영향을 받지 않음을 나타냅니다.

  • 새 행 그룹을 만들거나 기존 행 그룹의 상태를 변경하는 활동이 없는 기간 동안 이 쿼리를 실행합니다. 예를 들어 다음 활동은 행 그룹의 상태를 수정할 수 있습니다. 인덱스 빌드, 인덱스 재구성, 대량 삽입, 델타 저장소 압축 튜플 이동기.

    쿼리를 실행하기 전에 추적 플래그 634를 사용하여 백그라운드 튜플 이동기 작업을 사용하지 않도록 설정할 수 있습니다. 백그라운드 작업을 사용하지 않도록 설정하려면 DBCC TRACEON( 634 , -1 )을 사용합니다. 쿼리 실행이 완료되면 DBCC TRACEOFF ( 634 , -1 ) 명령을 사용하여 백그라운드 작업을 다시 사용하도록 설정해야 합니다.

    또한 이 쿼리가 실행되는 동안 columnstore 인덱스를 사용하는 테이블에 데이터를 삽입하는 BULK INSERT/BCP/SELECT-INTO 명령이 없는지 확인합니다.

    쿼리가 가양성 반환을 방지하려면 다음 단계를 사용하는 것이 좋습니다.

상태

Microsoft에서 이는 "적용 대상" 섹션에 나열된 Microsoft 제품에서의 문제임을 확인했습니다.