자신의 답변에서 어느 것이 더 낫습니까? 아이덴티티 열 또는 생성 된 고유 ID 값? mrdenny는 말한다 :
SQL Denali가 나오면 ID보다 효율적인 시퀀스를 지원하지만 더 효율적인 무언가를 만들 수는 없습니다.
확실하지 않아요. Oracle의 시퀀스를 알고 있으면 삽입을위한 트리거를 작성하거나 각 삽입을 스토어드 프로 시저 호출로 캡슐화하거나 임시 삽입을 수행 할 때 순서를 올바르게 사용하는 것을 잊지 않도록기도해야합니다.
시퀀스의 장점이 너무 분명하다는 것을 의심합니다.
답변
여기에도 대답하겠습니다. 그것은 방법 IDENTITY
과 SEQUENCE
작업 의 내부 와 관련이 있습니다.
을 사용 IDENTITY
하면 SQL Server는 값을 메모리에 미리 캐시하여 쉽게 사용할 수 있습니다. 자세한 내용은 Martin Smith의 답변 을 참조하십시오. 값이 사용되면 백그라운드 프로세스에서 더 많은 값을 생성합니다. 당신이 상상할 수 있듯이이 풀은 꽤 빨리 실행될 수 있으며 응용 프로그램은 값을 생성하는 백그라운드 프로세스의 자비에 맡겨집니다.
을 사용 SEQUENCE
하면 SQL Server에서 캐시 크기를 정의 할 수 있습니다. SQL Server는 실제로 캐시에 값을 유지하지 않지만 현재 값과 최상위 값만 유지하므로 값을 만드는 데 필요한 IO의 양이 크게 줄어 듭니다.
캐시를 너무 높게 설정하지 않으면 사용할 수있는 수가 줄어 듭니다. SQL Server가 충돌하면 사용되지 않은 현재 캐시 범위에 지정된 값이 손실됩니다.
행 삽입의 경우 다음과 같이 열의 기본값을 지정하십시오.
DEFAULT (NEXT VALUE FOR Audit.EventCounter),
답변
Itzik Ben Gan 기사 가 작성된 이래로 하드 코딩 된 캐시 크기 10은 IDENTITY
변경된 것으로 보입니다. 에서 이 연결 항목에 대한 의견
사전 할당의 크기는 ID 속성이 정의 된 열의 데이터 형식 크기를 기반으로합니다. SQL Server 정수 열의 경우 서버는 1000 개의 값 범위로 ID를 미리 할당합니다. bigint 데이터 유형의 경우 서버는 10000 값 범위로 미리 할당됩니다.
T-SQL 쿼리의 책은 다음 표를 포함하지만,이 값은 문서화 또는 변경되지 보장되지 않습니다 것을 강조한다.
+-----------------+-----------+
| DataType | CacheSize |
+-----------------+-----------+
| TinyInt | 10 |
| SmallInt | 100 |
| Int | 1,000 |
| BigInt, Numeric | 10,000 |
+-----------------+-----------+
이 기사에서는 다양한 시퀀스 캐시 크기와 삽입 배치 크기를 테스트하고 다음과 같은 결과를 얻습니다.
큰 인서트의 경우 IDENTITY
성능이 우수함을 보여주는 것으로 보입니다 SEQUENCE
. 그러나 캐시 크기 1,000은 테스트하지 않으며 결과는 하나의 테스트입니다. 다양한 배치 크기의 인서트가있는 캐시 크기 1,000을 구체적으로 살펴보면 다음과 같은 결과를 얻었습니다 (각 배치 크기를 50 회 시도하고 결과를 아래의 모든 시간을 μs로 집계).
+------------+-----------+-----------+-----------+-----------+-----------+-----------+
| | Sequence | Identity |
| Batch Size | Min | Max | Avg | Min | Max | Avg |
+------------+-----------+-----------+-----------+-----------+-----------+-----------+
| 10 | 2,994 | 7,004 | 4,002 | 3,001 | 7,005 | 4,022 |
| 100 | 3,997 | 5,005 | 4,218 | 4,001 | 5,010 | 4,238 |
| 1,000 | 6,001 | 19,013 | 7,221 | 5,982 | 8,006 | 6,709 |
| 10,000 | 26,999 | 33,022 | 28,645 | 24,015 | 34,022 | 26,114 |
| 100,000 | 189,126 | 293,340 | 205,968 | 165,109 | 234,156 | 173,391 |
| 1,000,000 | 2,208,952 | 2,344,689 | 2,269,297 | 2,058,377 | 2,191,465 | 2,098,552 |
+------------+-----------+-----------+-----------+-----------+-----------+-----------+
더 큰 배치 크기의 경우 IDENTITY
버전이 일반적으로 더 빠릅니다 .
TSQL 쿼리 책은 IDENTITY
시퀀스보다 성능 이점이있는 이유도 설명합니다 .
는 IDENTITY
테이블의 특정와 SEQUENCE
없습니다. 로그 버퍼를 플러시하기 전에 재해가 삽입 중반에 닥친 경우 복구 프로세스가 삽입을 취소하기 때문에 복구 된 ID가 이전 ID인지 여부는 중요하지 않으므로 SQL Server는 모든 ID에서 로그 버퍼를 강제로 플러시하지 않습니다. 캐시 관련 디스크 쓰기. 그러나 순서이가 되어 데이터베이스 외부를 포함하여 – 값이 목적을 위해 이용 될 수있는대로 시행. 따라서 위의 예에서 삽입 횟수가 백만이고 캐시 크기가 1,000 인 경우 이는 1,000 회의 로그 플러시입니다.
재현 할 스크립트
DECLARE @Results TABLE(
BatchCounter INT,
NumRows INT,
SequenceTime BIGINT,
IdTime BIGINT);
DECLARE @NumRows INT = 10,
@BatchCounter INT;
WHILE @NumRows <= 1000000
BEGIN
SET @BatchCounter = 0;
WHILE @BatchCounter <= 50
BEGIN
--Do inserts using Sequence
DECLARE @SequenceTimeStart DATETIME2(7) = SYSUTCDATETIME();
INSERT INTO dbo.t1_Seq1_cache_1000
(c1)
SELECT N
FROM [dbo].[TallyTable] (@NumRows)
OPTION (RECOMPILE);
DECLARE @SequenceTimeEnd DATETIME2(7) = SYSUTCDATETIME();
--Do inserts using IDENTITY
DECLARE @IdTimeStart DATETIME2(7) = SYSUTCDATETIME();
INSERT INTO dbo.t1_identity
(c1)
SELECT N
FROM [dbo].[TallyTable] (@NumRows)
OPTION (RECOMPILE);
DECLARE @IdTimeEnd DATETIME2(7) = SYSUTCDATETIME();
INSERT INTO @Results
SELECT @BatchCounter,
@NumRows,
DATEDIFF(MICROSECOND, @SequenceTimeStart, @SequenceTimeEnd) AS SequenceTime,
DATEDIFF(MICROSECOND, @IdTimeStart, @IdTimeEnd) AS IdTime;
TRUNCATE TABLE dbo.t1_identity;
TRUNCATE TABLE dbo.t1_Seq1_cache_1000;
SET @BatchCounter +=1;
END
SET @NumRows *= 10;
END
SELECT NumRows,
MIN(SequenceTime) AS MinSequenceTime,
MAX(SequenceTime) AS MaxSequenceTime,
AVG(SequenceTime) AS AvgSequenceTime,
MIN(IdTime) AS MinIdentityTime,
MAX(IdTime) AS MaxIdentityTime,
AVG(IdTime) AS AvgIdentityTime
FROM @Results
GROUP BY NumRows;