반응형
/********************************************************************************************
-- Title : [2k5] char, varchar, ansi_padding 별 데이터/인덱스 페이지 비교
-- Reference : dbrang.tistory.com
-- Key word : ansi_padding dbcc page viewer
********************************************************************************************/
-- 뒷 공간을 어떻게 처리하는지 페이지 보며 테스트...
-- 'C    '이런 데이터가 어떻게 처리되는지 봤다..ㅡㅡ;;
-- 결론은? 데이터/인덱스 페이지 저장은 ansi_padding에 따라 다른데 결과는 동일하고
-- 실행계획도 동일하당...
-- char/varchar간 뒷 공간에 따른 실행계획 차이는 없지만, 유니코드/비유니코드간에는
-- 확연히 틀어진당...

--테이블 생성
drop table ttt;
create table ttt
(a int not null identity primary key
, ch char(10) not null
, vc varchar(10) not null
);

--셈플 데이터 입력
insert into ttt
select 'a','b' union all
select 'c ','d ' union all
select 'e  ','f   ' union all
select 'c','d' union all
select 'e','f' union all
select 'g','e';

declare @i int;
set @i = 1
while (@i <= 100000)
begin
    insert into ttt values(cast(@i as char(10)), cast(@i as varchar(10)));
    set @i = @i + 1;
end;

--인덱스 생성
create index ix_ttt_ch
on ttt(ch);
create index ix_ttt_vc
on ttt(vc);

--확인
select * from ttt;
select *, len(ch) "len_ch", len(vc) "len_vc"
from ttt; --RTRIM이 된것처럼 무조건 문자 길이 표시
select *, datalength(ch) "datalength_nc", datalength(vc) "datalength_vc"
from ttt; -- CHAR는 무조건 10, VARCHAR는 RTRIM 안 된것처럼 공간까지 길이 표시

select * from ttt where ch = 'c';   --index seek(원본 ch'c ')
select * from ttt where vc = 'd';   --index seek(원본 vc'd ')
select * from ttt where ch = 'e ';  --index seek(원본 ch'e  ')
select * from ttt where vc = 'f ';  --index seek(원본 vc'f  ')
select * from ttt a inner join ttt b
on a.ch = b.vc where b.vc = 'e';    --index seek

--인덱스 삭제하고 다시
drop index ttt.ix_ttt_ch;
drop index ttt.ix_ttt_vc;

--확인
select * from ttt where ch = 'c';  
select * from ttt where vc = 'd';  
select * from ttt where ch = 'e '; 
select * from ttt where vc = 'f '; 
select * from ttt a inner join ttt b
on a.ch = b.vc where b.vc = 'e';    --모든 결과 동일(위에 위에 결과와)

char 'e__' 저장 데이터 페이지

varchar 'f__' 저장 데이터 페이지

char 'e__' 저장 인덱스 페이지

varchar 'f__' 저장 인덱스 페이지

-- ANSI_PADDING 옵션 변경
SET ANSI_PADDING OFF;

--테이블 생성
drop table ttt2;
create table ttt2
(a int not null identity primary key
, ch char(10) not null
, vc varchar(10) not null
);

--셈플 데이터 입력
insert into ttt2
select 'a','b' union all
select 'c ','d ' union all
select 'e  ','f   ' union all
select 'c','d' union all
select 'e','f' union all
select 'g','e';

declare @i int;
set @i = 1
while (@i <= 100000)
begin
    insert into ttt2 values(cast(@i as char(10)), cast(@i as varchar(10)));
    set @i = @i + 1;
end;

--인덱스 재생성
create index ix_ttt_ch2
on ttt2(ch);
create index ix_ttt_vc2
on ttt2(vc);

--확인
select * from ttt2;
select *, len(ch) "len_ch", len(vc) "len_vc"
from ttt2; --RTRIM이 된것처럼 무조건 문자 길이 표시
select *, datalength(ch) "datalength_nc", datalength(vc) "datalength_vc"
from ttt2; -- CHAR는 무조건 10, VARCHAR는 RTRIM 된것처럼 공간 제외하고 길이 표시

select * from ttt2 where ch = 'a';    --index seek(원본 ch'c ')
select * from ttt2 where vc = 'd';    --index seek(원본 vc'd ')
select * from ttt2 where ch = 'e';    --index seek(원본 ch'e  ')
select * from ttt2 where vc = 'f';    --index seek(원본 vc'f  ')
select * from ttt2 a inner join ttt b
on a.ch = b.vc where b.vc = 'e';      --index seek

 
ansi padding off : char 'e__' 저장 데이터 페이지

ansi padding off : varchar 'f__' 저장 데이터 페이지

ansi padding off : char 'e__' 저장 인덱스 페이지

ansi padding off : varchar 'f__' 저장 인덱스 페이지
 
--테이블 상호간 조인
select * from ttt a inner join ttt2 b
on a.ch = b.ch where b.ch = 'e';
select * from ttt a inner join ttt2 b
on a.vc = b.vc where b.vc = 'f';

--인덱스 제거
drop index ttt.ix_ttt_ch;
drop index ttt.ix_ttt_vc;
drop index ttt2.ix_ttt_ch2;
drop index ttt2.ix_ttt_vc2;

--테이블 상호간 조인
select * from ttt a inner join ttt2 b
on a.ch = b.ch where b.ch = 'e '
select * from ttt a inner join ttt2 b
on a.vc = b.vc where b.vc = 'f       ';

--유니코드 테스트
select * from ttt a inner join ttt2 b
on a.ch = b.ch where b.ch = 'e'
select * from ttt a inner join ttt2 b
on a.vc = b.vc where b.vc = N'f  ';

반응형

+ Recent posts