귀하의 질문에 따르면 테이블 변수와 임시 테이블을 둘러싼 일반적인 오해에 굴복했습니다.
나는 DBA 사이트에 대한 광범위한 답변을 작성했습니다 에서 두 개체 유형의 차이점을 살펴보면서 . 이것은 또한 디스크 대 메모리에 대한 귀하의 질문을 해결합니다 (두 가지 행동에 큰 차이가 없었습니다).
테이블 변수와 로컬 임시 테이블의 사용시기에 관한 제목의 질문과 관련하여 항상 선택할 수있는 것은 아닙니다. 예를 들어 함수에서 테이블 변수 만 사용할 수 있으며 하위 범위의 테이블에 써야하는 경우 테이블 만 #temp
수행됩니다 (테이블 값 매개 변수는 읽기 전용 액세스 허용 ).
선택의 여지가있는 경우 몇 가지 제안 사항이 아래에 나와 있습니다 (가장 안정적인 방법은 특정 작업으로 두 가지를 모두 테스트하는 것임).
테이블 변수에서 작성할 수없는 인덱스가 필요한 경우 물론 #temporary
테이블이 필요 합니다. 그러나 이에 대한 자세한 내용은 버전에 따라 다릅니다. SQL Server 2012 이하의 경우 테이블 변수에서 만들 수있는 유일한 인덱스는 UNIQUE
또는PRIMARY KEY
제약 조건을 . SQL Server 2014에는에서 사용할 수있는 옵션의 하위 집합에 대한 인라인 인덱스 구문이 도입되었습니다 CREATE INDEX
. 필터링 된 인덱스 조건을 허용하기 위해 확장되었습니다. 그러나 INCLUDE
-d 컬럼 또는 columnstore 인덱스가있는 인덱스는 여전히 테이블 변수에서 작성할 수 없습니다.
테이블에서 많은 수의 행을 반복적으로 추가 및 삭제하려면 테이블을 사용 #temporary
하십시오. 지원 TRUNCATE
( DELETE
대형 테이블 보다 효율적 ) 및 추가 인서트 다음에 오는 추가 인서트 TRUNCATE
는DELETE
여기에 설명 것처럼 있습니다 .
- 많은 수의 행을 삭제하거나 업데이트 할 경우 임시 테이블이 행 변수 공유를 사용할 수있는 경우 테이블 변수보다 훨씬 더 잘 수행 될 수 있습니다 (예를 들어 아래의 "행 세트 공유 효과"참조).
- 테이블을 사용하는 최적의 계획이 데이터에 따라 다를 경우 테이블을 사용
#temporary
하십시오. 이는 통계에 따라 계획에 따라 데이터에 따라 동적으로 재 컴파일 될 수 있도록합니다 (저장 프로 시저 의 캐시 된 임시 테이블의 경우 재 컴파일 동작). 을 별도로 이해해야 함).
- 테이블을 사용하는 쿼리에 대한 최적 계획이 변경되지 않을 경우 통계 작성의 오버 헤드를 건너 뛰고 다시 컴파일하기 위해 테이블 변수를 고려할 수 있습니다 (원하는 계획을 수정하는 데 힌트가 필요할 수 있음).
- 테이블에 삽입 된 데이터의 소스가 잠재적으로 비쌉니다
SELECT
명령문의 경우 테이블 변수를 사용하면 병렬 계획을 사용하여이 가능성을 차단할 수 있습니다.
- 외부 사용자 트랜잭션의 롤백에서 살아 남기 위해 테이블의 데이터가 필요한 경우 테이블 변수를 사용하십시오. 가능한 유스 케이스는 긴 SQL 배치에서 다른 단계의 진행 상황을 로깅하는 것일 수 있습니다.
#temp
사용자 트랜잭션 내 에서 테이블을 사용하는 경우 잠금은 테이블 변수보다 오래 지속될 수 있으며 (잠재적으로 트랜잭션 끝과 잠금 유형 및 분리 레벨에 따라 명령문 끝까지) 유지 될 수 있습니다 tempdb
. 사용자 거래가 종료됩니다. 따라서 이것은 테이블 변수 사용을 선호 할 수 있습니다.
- 저장된 루틴 내에서 테이블 변수와 임시 테이블을 모두 캐시 할 수 있습니다. 캐시 된 테이블 변수에 대한 메타 데이터 유지 보수는 테이블에 대한 메타 데이터 유지 보수보다 적습니다
#temporary
. Bob Ward는 tempdb
프레젠테이션 에서 동시성이 높은 조건에서 시스템 테이블에 대한 추가 경합이 발생할 수 있다고 설명합니다. 또한 소량의 데이터를 처리 할 때 성능에 상당한 차이가 생길 수 있습니다 .
행 집합 공유의 효과
DECLARE @T TABLE(id INT PRIMARY KEY, Flag BIT);
CREATE TABLE #T (id INT PRIMARY KEY, Flag BIT);
INSERT INTO @T
output inserted.* into #T
SELECT TOP 1000000 ROW_NUMBER() OVER (ORDER BY @@SPID), 0
FROM master..spt_values v1, master..spt_values v2
SET STATISTICS TIME ON
/*CPU time = 7016 ms, elapsed time = 7860 ms.*/
UPDATE @T SET Flag=1;
/*CPU time = 6234 ms, elapsed time = 7236 ms.*/
DELETE FROM @T
/* CPU time = 828 ms, elapsed time = 1120 ms.*/
UPDATE #T SET Flag=1;
/*CPU time = 672 ms, elapsed time = 980 ms.*/
DELETE FROM #T
DROP TABLE #T
tempDB
"메모리에"있다는 신화입니다. 또한 테이블 변수는 항상 쿼리 최적화 프로그램에 의해 정확히 한 행을 보유하는 것으로 간주됩니다. 더 많은 행이 있으면 실행 계획이 심각하게 잘못 될 수 있습니다.