공부를 시작한지 얼마 안된 초보입니다. 인덱스 부분을 공부하다가 궁금해서 이렇게 글을 남기게되었습니다.
클러스터 인덱스가 있는 테이블에서 넌클러스터 인덱스의 컬럼으로 실행계획에서 쿼리문 비교할때 Index Scan 하는 것과 Index Seek 와 Key LookUP 을 내부조인해서 결과를 보여주는것이 많은 차이점이 있는 것인가요? 궁금해서 여쭙게되었습니다 ㅠㅠ 말이좀이상하면 수정하도록하겠습니다
Comment 13
-
Hisory
2014.04.25 13:32
-
꿈벵이
2014.04.25 14:14
이내용은 제가본거랑 같네요 ㅎㅎ 답글 감사드립니다.
제가 글을 잘못썻나봐요 제가 원하는건
인덱스 스캔이 인덱스 시크와 키룩업 또는 인덱스 시크와 알아이디 룩업이 (위의 주소에서 알려주는 RID 룩업 발생하는 그림)과
별만 차이가 없는건지 궁금해서 여쭙게된거에요 ㅠㅠ
답변감사드립니다
-
항해자™
2014.04.26 01:34
-
아는데로만 설명해보겠습니다.
클러스터드 인덱스가 있는 테이블의 경우 데이터는 클러스터드 인덱스의 키로 정렬이됩니다.
이 키로 데이터를 찾을 경우 "Clustered Index Seek"가 발생하게 됩니다.
클러스터드 인덱스가 없는 테이블의 경우 데이터는 추가된 순서대로 쌓이게 됩니다. 그래서 힙이라고 하죠.
이때 넌클러스터드 인덱스를 만들게 되면 넌클러스터드 인덱스의 리프레벨에는 데이타의 위치를 가르키는 RID가 기록됩니다.
넌클러스터드 인덱스로 데이터를 찾을 경우에는 그래서 "RID Lookup"이 밸생하게 됩니다.
근데 클러스터드 인덱스가 있는 테이블에 넌클러스터드 인덱스를 만들면 이 인덱스의 리프레벨에는 RID가 아닌 클러스터드 인덱스의 키가 기록됩니다.
그래서 이 넌클러스터드 인덱스로 데이터를 찾을 경우에는
넌클러스터드 인덱스의 리프레벨에서 클러스터드 인덱스의 키를 확인한 후 이 키를 이용해서 데이터를 찾는 "Key Lookup"이 발생합니다.
"Index Scan"이란 이런겁니다.
주소록 테이블에 전화번호로 인덱스를 만들었습니다.
근데 찾고 싶은 데이터는 전화번호의 4번째가 7이고 다섯번째와 여섯번째의 차가 3인 그런 데이타입니다. -_-;;
우리가 전화번호부를 이용해서 이런 데이터를 찾으려고 해도... 결국 전화번호부 책을 몽땅 뒤질수밖에 없죠.
SQL SERVER도 마찬가지입니다. 인덱스를 이용해서 저런 데이타를 찾을 수가 없습니다.
그래서 결국 테이블을 몽땅 스켄합니다. 이것이 "Clustered Index Scan" 또는 "Table Scan"
근데 찾으려는 데이타가 인덱스의 키에 포함되어 있을 경우 테이블을 몽땅 뒤지는것보다 인덱스를 뒤지는게 더 빠릅니다.
이유는 인덱스 페이지가 더 작을것이기 때문이죠. 이때 발생하는것이 "Index Scan"
더 자세한 설명과 이 댓글에 대한 수정은 다음분이... -_-;;
-
항해자™
2014.04.28 09:41
마지막 부분은 index seek 설명 같은데요??ㅎㅎ
(태클 아닙니다;;) -
"Index Seek"의 경우는 "010-9999-8888 을 찾아주세요" 할때 인덱스에 일치하는 데이타가 있는지 찾을때 발생하는 거구요.
전화번호의 다섯번째 (하이픈 뒤)가 7이고 여섯번째와 일곱번째의 차가 3인 데이타
쿼리로 표현하자면 where 전화번호 like '___-7%' AND ABS(SUBSTRING(전화번호, 6, 1) - SUBSTRING(전화번호, 7, 1)) = 3 이런거죠.
도저히 인덱스를 사용할 수 없는 경우입니다.
이런경우는 데이터를 몽땅 스캔해야 하는데 전화번호부 컬럼으로 인덱스가 있다면 데이터 전체 보다는 인덱스를 스캔합니다.
인덱스는 데이타의 일부이므로 무조건 데이터보다는 작죠.
책을 예로 다시 설명해보면
보통 기술서적들 보면 맨 뒤에 키워드를 인덱스로 만들어놨스니다.
SQL 관련 서적을 예로 들면 "클러스터드 인덱스"에 대해 설명해놓은 페이지를 찾으려면
"ㅋ"섹션에서 "클러스터드 인덱스" 키워드를 찾은 후 517페이지 (<- 이게 RID) 에 있다는 걸 확인한 후 517페이지를 펼치게 됩니다.
이런게 "Index Seek"
근데 키워드 중에 중간에 "덱"이 들어간 페이지를 찾고 싶으면??
인데스 a~z ㄱ~ㅎ까지 몽땅 확인해야죠? 중간에 "덱"이런거 들어간 키워드가 있나...
이런 동작이 "Index Scan"입니다.
"Index Seek"동작이나 "Index Scan"동작은 어쨋든 인덱스 페이지에서 인덱스 키를 찾는 동작입니다.
이 동작이 끝나고 나면 데이터 페이지로 이동하기 위해 "RID Lookup"이나 "Key Lookup"을 하게 되죠.
클러스터드 인덱스가 있을때는 Key Lookup 넌클러스터드만 있다면 RID Lookup을 하게 됩니다.
근데 만약에 원하는 데이타가 인덱스 키 안에 모두 포함되어 있다면
말하자면 전화번호부 테이블에서 "전화번호, 이름"으로 인덱스가 만들어져 있는데
select 전화번호, 이름 from 전화번호부 where 전호번호 = '010-9999-8888' 이런 쿼리를 날린다면
전화번호와 이름이 모두 인덱스 페이지에 있기 때문에 더 이상 데이터 페이지로 이동하지 않아도 모든 데이터를 확인 할 수 있습니다.
그러면 Lookup 동작 자체를 안하게 됩니다.
이런걸 "커버드 인덱스"라고 합니다.
따로 룩업을 안하고 인덱스 페이지에서 모든 데이터를 가져가는것이 마치 클러스터드 인덱스의 동작과 비슷합니다.
그래서 성능이 클러스트드 인덱스에 필적한다고 하죠.
사실 커버드 인덱스란 인덱스의 종류가 따로 있는 것이 아니라 어떤 쿼리가 인덱스 컬럼 내에서만 select 할때
그때 사용된 인덱스가 쿼리를 커버하는 것이죠.
-
맨즈밤
2014.04.28 11:34
와~~~~대단합니다. 책의 한 챕터를 읽는 느낌이었습니다. 살짝 덧붙이자면 스캔시에 미리읽기가 적용되면 , 더 많은 데이터를 메모리로 퍼올릴수 있습니다. 생각보다 scan의 효율이 높을수 있다는 뜻입니다..
-
항해자™
2014.04.28 19:28
글을 다시 읽어보니 제가 잘못 봤었네요;; -
넵 ^^
-
꿈벵이
2014.04.29 14:19
안녕하세요^^ 자세한 설명과 답글 감사드립니다.
궁금한걸 해결하는 동시에 한가지더 궁금한 점이 남아 이렇게 질문드리게 되었습니다.
예를들어 두개의 질의를 비교하려고 실행계획을 수행하였을때 하나는 Index Scan 이 나타나고
또다른 하나는 아래의 그림과같이 Index Seek + Key LookUp이 나타납니다. 물론 이부분은 위에 말씀해주신것처럼 클러스터 인덱스를 사용하여 키룩업이 발생한것입니다. 또한 커버된 질의를 사용하지 못하기때문에 나타난 현상이지만 성능면에서 인덱스 스캔 이나 아래의 그림과 같이 Index Seek + Key LookUp은 똑같다고 볼수가 있는건가요? 이것이 궁금해 이렇게 질문드리게되었습니다.
죄송합니다 ㅠㅠ
-
이쯤에서 제 밑천이 보이네요... -_-;;
아마도 이번 제 설명에는 지적하시는 분이 나타날듯...
예를 들어 100만건 데이터가 있는 테이블에 인덱스를 만들면 인덱스의 리프레벨에도 데이타가 100만건이 있을겁니다.
인덱스 스켄이란 이 100만건을 모두 스켄해봤다는 뜻입니다.
인덱스 시크+키룩업은 B트리를 타고 정확히 일치하는 몇개의 데이터만 접근 한 후 클러스터드 인덱스를 확인하고 룩업을 했다는 뜻이죠.
그러니 아마도 같을 수는 없을겁니다.
SQL SERVER에서 성능이란 결국 CPU를 얼마나 쓰느냐 그리고 DISK에서 얼마나 읽어오느냐의 차이인데
스켄의 경우 DISK I/O가 훨씬 많아지게 되죠.
프로파일러로 두 쿼리를 비교해서 I/O와 CPU를 비교해보시기 바랍니다.
-
꿈벵이
2014.04.29 15:10
매번 감사드립니다. 이제서야 이해를 하게되었네요
처음 데이터 천건으로 하니 인덱스 스켄으로 실행계획이 나오다가 천만건 정도 데이터를 넣어보니 이렇게 뜨기에
옵티마이저가 스캔보다는 더빠르니 이렇게 선택햇구나하고 그냥있었는데 이렇게 알고 가게되었습니다.
정말 감사드립니다^^
-
minsouk
2014.04.30 14:57
좀 보이지만 그냥 넘어갑니다. ^.^
http://ksewookk.blog.me/100117148425
http://ksewookk.blog.me/100117148425