Index IGNORE_DUP_KEY 옵션 TEST
No |
방법 |
문제점 |
1 |
클러스터 Key IGNORE_DUP_KEY 옵션 |
온라인 Reindex가
되지 않음 -DBA 상에서 관리 이슈 있음 |
2 |
유니크 Index를 생성하고 IGNORE_DUP_KEY 옵션 |
No 1의 문제점 해결 |
3 |
쿼리 문을 수정 하는 방법 |
Insert 문을 수정해서 입력 하는 방법 -- Insert 문 수정 with except INSERT dbo.PKDUP (pk) select i from dbo.DUMP_INSERT where i between 10000 and 130000 except select pk from dbo.PKDUP
-- merge 문 사용 MERGE dbo.PKDUP AS b USING (SELECT i FROM dbo.DUMP_INSERT WHERE i BETWEEN 10000 AND 130000) AS s ON s.i = b.pk WHEN NOT MATCHED THEN INSERT (pk) VALUES (s.i);
|
4 |
INSTEAD OF trigger 사용 방법 |
3번 으로 하면 가장 좋으나 대량의 bulk 성으로 입력을 해야
하는 경우 대안이 될 수 있을 것 같음 |
CREATE TABLE dbo.PK_DUP ( pk int NOT NULL, CONSTRAINT PK_PK_DUP PRIMARY KEY (pk) WITH (IGNORE_DUP_KEY = ON) ); GO select * from sys.indexes where object_id = object_id ('PK_DUP') -- Unique values INSERT dbo.PK_DUP (pk) VALUES (1), (3), (5); GO -- key 3 already exists INSERT dbo.PK_DUP (pk) VALUES (2), (3), (4); /* 중복 키가 무시되었습니다. (2개 행이 영향을 받음) */ select * from PK_DUP /* pk 1 2 3 4 5 */ /** Problem 1 : Rebild를 할 수 없다. **/ ALTER INDEX PK_PK_DUP ON dbo.PK_DUP REBUILD WITH (FILLFACTOR = 90, ALLOW_ROW_LOCKS = OFF, ONLINE = ON, IGNORE_DUP_KEY = ON); GO /* 메시지 1979, 수준 16, 상태 1, 줄 1 인덱스 옵션 ignore_dup_key는 PRIMARY KEY 또는 UNIQUE 제약 조건을 적용하므로 이 인덱스 옵션을 사용하여 인덱스 'PK_PK_DUP'을(를) 변경할 수 없습니다. */ |
[성능 TEST No2]
-- 새로운 Idea -- 유니크 key를 만들어서 처리 한다. CREATE TABLE dbo.PKDUP (pk int NOT NULL CONSTRAINT PK_PKDUP PRIMARY KEY); GO INSERT dbo.PKDUP (pk) VALUES (1), (2), (3); GO -- New constraint (or index) with IGNORE_DUP_KEY, added ONLINE ALTER TABLE dbo.PKDUP ADD CONSTRAINT UIDX_PKDUP UNIQUE NONCLUSTERED (pk) WITH (IGNORE_DUP_KEY = ON, ONLINE = ON); select * from sys.indexes where object_id = object_id ('PKDUP')
-- key 3을 입력 한다. INSERT dbo.PKDUP (pk) VALUES (3), (4), (5); GO /*중복 키가 무시되었습니다. */ SELECT pk FROM dbo.PKDUP; /* pk 1 2 3 4 5 */ -- Problem 1 해결 ALTER INDEX PK_PKDUP ON dbo.PKDUP REBUILD WITH (FILLFACTOR = 90, ALLOW_ROW_LOCKS = OFF, ONLINE = ON); GO ALTER INDEX UIDX_PKDUP ON dbo.PKDUP REBUILD WITH (FILLFACTOR = 100, ALLOW_ROW_LOCKS = OFF, ONLINE = ON); GO No1의 문제는 해결 되나 성능 상의 이슈로 입력 하는 데이터와 기존 데이터를 비교 하는 추가 적인 작업 단계가 늘어나면서
예상 비용이 3배 정도 증가 함. |
[성능 TEST No3]
CREATE TABLE DUMP_INSERT ( i int ) set nocount on declare @i int set @i =1 while (@i < 10000 ) begin insert into DUMP_INSERT values ( @i ) set @i = @i + 1 end insert into PKDUP select * from DUMP_INSERT set nocount on declare @i int set @i =90000 while (@i < 110001 ) begin insert into DUMP_INSERT values ( @i ) set @i = @i + 1 end -- 유니크 Index 삭제 alter table dbo.PKDUP drop constraint UIDX_PKDUP set nocount on declare @i int set @i =120001 while (@i < 150001 ) begin insert into DUMP_INSERT values ( @i ) set @i = @i + 1 end
-- Insert 문 수정 with except INSERT dbo.PKDUP (pk) select i from dbo.DUMP_INSERT where i between 10000 and 130000 except select pk from dbo.PKDUP
n 여전히 Buffer pool 공간은 사용 하지만 예상 비용은 0.96
-- merge 문 사용 MERGE dbo.PKDUP AS b USING (SELECT i FROM dbo.DUMP_INSERT WHERE i BETWEEN 10000 AND 130000) AS s ON s.i = b.pk WHEN NOT MATCHED THEN INSERT (pk) VALUES (s.i);
- 비용은 증가하나 Buffer pool 공간은 사용하지 않음
|
성능 TEST No4]
-- INSTEAD OF trigger -- INSTEAD OF 트리거는 트리거 문의 표준 동작을 무시합니다. -- 따라서 이 트리거를 사용하여 하나 이상의 열에서 오류나 값을 확인하고 행을 삽입, 업데이트 또는 삭제하기 전에 추가 동작을 수행할 수 있습니다. -- INSTEAD OF 트리거가 제약 조건을 위한 하면 AFTER 트리거는 실행되지 않습니다. CREATE TRIGGER tI_PKDUP ON DBO.PKDUP INSTEAD OF INSERT AS BEGIN SET NOCOUNT ON INSERT dbo.PKDUP (pk) SELECT PK FROM INSERTED except select pk from dbo.PKDUP END GO INSERT dbo.PKDUP (pk) SELECT i FROM dbo.DUMP_INSERT WHERE i BETWEEN 10000 AND 130000
- Mearge랑 비슷한 예상 비용이 발생 함. 트리거 사용을 권하지는 않지만 대량 데이터 입력으로 인해 No3 번이 불가능 할 때 고려해 볼 만 함.
|
'Peformance Tuning' 카테고리의 다른 글
파티션 테이블 - 문제점, 주의 사항 (0) | 2012.11.19 |
---|---|
query plan의 실행 옵션 보기 (0) | 2012.01.29 |
Dynamic Management Views (0) | 2012.01.22 |
Hash Join 제약. (0) | 2011.10.10 |