문제

우리는 동일한 두 개의 '인스턴스'사이의 조인에서 생성 된 레코드를 통해 커서를 설정하려고합니다. 거대한 테이블 (150m 이상의 레코드).

다음과 같은 예외 메시지가 나옵니다.

'기본'파일 그룹이 가득 차기 때문에 'dbo.sort 임시 실행 저장소 : 165282123350016'에 대한 공간을 할당 할 수 없습니다. 불필요한 파일을 삭제하거나 파일 그룹에서 객체를 삭제하거나 파일 그룹에 추가 파일을 추가하거나 파일 그룹의 기존 파일에 대해 AutoGrowth를 설정하여 디스크 공간을 만듭니다.

이에 대한 이유를 아는 사람이 있습니까? 또는 아래의 쿼리를보다 효율적으로 만드는 방법은 무엇입니까?

나는 그것이 어디에서 발생한다는 것을 발견했다 DECLARE CURSOR 그리고 첫 번째 FETCH NEXT, 그러나 나는 그것이 사이에 있는지 아직 모른다 ...

  • DECLARE CURSOR 그리고 OPEN

또는 그 사이

  • OPEN 그리고 첫 번째 FETCH NEXT.

자세한 내용 : SQL 문은 다음과 같습니다.

DECLARE cData CURSOR LOCAL FORWARD_ONLY READ_ONLY
FOR
  SELECT ...
  FROM HugeTable HT1 JOIN HugeTable HT2 ON .. 
  JOIN Table3 ON .. JOIN Table4 ON .. JOIN Table5 ON ..
  WHERE ...
  ORDER BY HT1..., HT1...

INSERT INTO SysLog (Description) VALUES ('A')

OPEN cData
BEGIN TRANSACTION ProcessData
  -- Currently trying new logging here:
  -- INSERT INTO SysLog (Description) VALUES ('B') 
  FETCH NEXT FROM cData INTO ...
  INSERT INTO SysLog (Description) VALUES ('C')
  ... etc.

내가 얻는 마지막 로그 메시지는 'a'인 다음 1 시간 후에 위에서 설명한 메시지가 실패하여 'C'에 도달하지 못합니다. 나는 지금 'b'지점에서 로깅을 시도하고있다.


요청시 정확한 SQL 표현식을 게시합니다.

DECLARE cSource CURSOR LOCAL FORWARD_ONLY READ_ONLY
FOR
    SELECT MD.sFieldName, 
        MD.sFieldValue, 
        TR.sTargetDataType,
        MD2.sFieldValue AS sUniqueID,
        TR.sTargetTableName,
        TR.sTargetFieldName,
        I.iRefCustomerID, 
        I.iInterfaceID, 
        IL.iRefInterfaceSessionID
    FROM MasterData MD
    JOIN MasterData MD2
        ON MD.iRowIndex = MD2.iRowIndex
        AND MD.iBatchNumber = MD2.iBatchNumber
        AND MD.sTableName = MD2.sTableName 
        AND MD2.sFieldName = 'sUniqueID'
    JOIN SourceTargetRelation TR
        ON MD.sFieldName = TR.sSourceFieldName
        AND MD.sTableName = TR.sSourceTableName
    JOIN InterfaceLog IL
        ON IL.iInterfaceLogID = MD.iBatchNumber
    JOIN Interface I
        ON I.iInterfaceID = IL.iRefInterfaceID
        AND TR.iRefSystemID = I.iRefSystemID
    WHERE
        MD.iBatchNumber = @iBatchNumber
    ORDER BY MD.sTableName, MD.iRowIndex

Quassnoi의 업데이트 된 답변 후에는 원래 색인을 표에 게시합니다.

이 테이블에 열이없는 비 클러스터 인덱스가 있습니다. iBatchNumber, sFieldName, sTableName, iRowIndex. 그리고 그 지수는 있습니다 sFieldValue 포함 된 열로.


Quassnoi가 제안한 것처럼 (그리고 지금 왜 그런지 이해한다고 생각합니다) 나는이 순서로 열을 갖도록 색인을 변경했습니다. iBatchNumber, sTableName, iRowIndex, sFieldName. 그리고 나는 사용한다 sFieldValue 포함 된 열로. 실행 계획에는 어떤 것이 포함되어 있지 않습니다 SORT 더 이상, 실행 계획의 단계 수는 원본의 절반 미만이므로 더 빠릅니다 ...

도움이 되었습니까?

해결책

이에 대한 이유를 아는 사람이 있습니까? 또는 아래의 쿼리를보다 효율적으로 만드는 방법은 무엇입니까?

쿼리가 사용됩니다 ORDER BY.

정렬 및 정렬에는 임시 공간이 필요합니다. 당신은이 공간을 벗어났습니다.

이를 피하려면 거대한 테이블에 복합 색인을 만듭니다. (col_filter_1, col_filter_2, col_order_1, col_order_2), 어디 col_filter_n 필터링 된 열입니다 col_order_n 주문한 열입니다.

이러한 인덱스는 필터링 된 결과를 필터링하고 주문하는 데 사용할 수 있습니다.

실제 쿼리를 게시하면 (즉, 필터링하고 주문한 표현식), 그러한 색인을 만드는 방법을 더 정확하게 알려줄 수 있습니다.

업데이트:

쿼리에서 인덱스가 필요하다는 것을 알 수 있습니다. (iBatchNumber, sTableName, iRowIndex, sFieldName) (그와 같은 순서로).

당신이 만들면 도움이 될 수 있습니다 MD2 가입의 선도 :

WHERE
    MD2.iBatchNumber = @iBatchNumber
ORDER BY
    MD2.sTableName, MD2.iRowIndex

실행 계획을보고 아니오를 확인하십시오 SORT 작동이 사용됩니다.

다른 팁

왜 커서를 사용하고 있습니까? 특히 큰 테이블에서? 세트 기반으로 할 수없는 일은 무엇을하고 있습니까? Cursprs는 성능에 매우 나쁘고 다른 대안이 존재하는 경우 사용해서는 안됩니다. 커서없이 훨씬 더 잘 수행 할 수있는 선택된 레코드를 기반으로 다른 테이블에 삽입하는 경우.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top