거대한 테이블의 MSSQL 커서는 공간을 할당 할 수 없습니다
-
22-08-2019 - |
문제
우리는 동일한 두 개의 '인스턴스'사이의 조인에서 생성 된 레코드를 통해 커서를 설정하려고합니다. 거대한 테이블 (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는 성능에 매우 나쁘고 다른 대안이 존재하는 경우 사용해서는 안됩니다. 커서없이 훨씬 더 잘 수행 할 수있는 선택된 레코드를 기반으로 다른 테이블에 삽입하는 경우.