본문 바로가기

전공/DB

[DB 기술면접 질문 리스트] : 인덱스

-  RDBMS가 뭔가요? RDBMS의 특징 설명해보시겠어요?                                                               

  관계형 데이터베이스를 생성하고 수정하고 관리할 수 있는 소프트웨어입니다. 

 

RDBMS의 특징으로는

 모든 데이터를 2차원 테이블로 표현하며, 각  테이블의 단위는 row(record, tuple)과 column(field, item)으로 이루어져있습니다. sql을 사용해 Join 등의 관계형 연산을 하며, 하나의 고성능 머신에 데이터 저장하는 수직적 확장 방식입니다. 

따라서 "데이터가 자주 수정되는 경우", 혹은 "스키마가 변경될 여지가 없고, 명확한 스키마가 중요한 경우" 사용되는 것이 좋습니다.

    장점

    • 데이터의 일관성을 보증할 수 있음
    • 데이터베이스 설계 시 이미 불필요한 중복이 삭제됨
    • 정규화를 전제로 하고 있기 때문에 업데이트 시 비용이 적음(동일 컬럼은 동일 장소에 존재)

    단점

    • 테이블간테이블 간 관계를 맺고 있어 시스템이 커질 경우 JOIN문이 많은 복잡한 쿼리가 만들어질 수 있다.
    • 스키마로 인해 데이터가 유연하지 못하다. 나중에 스키마가 변경 될 경우 번거롭고 어렵다.
    • 성능 향상을 위해서는 서버의 성능을 향상 시켜야하는 Scale-up만을 지원합니다. 이로 인해 비용이 기하급수적으로 늘어날 수 있습니다.

    -  NoSQL에 대해 설명해주실 수 있나요?                                                                                      

      (Not Only SQL)의 약자로 관계형 데이터베이스가 아닌 다른 형태의 데이터 저장 기술입니다.

     RDBMS와는 달리 테이블 간 관계를 정의하지 않으며,  데이터 모델 자체가 독립적으로 설계되어있습니다. 따라서 데이터를 여러 서버에 분산시키는 분산형 구조에 용이하고, 대용량 데이터 처리에 적합합니다. 

    Update가 많이 이루어지지 않는 시스템이 좋으며 또한 막대한 데이터를 저장해야 해서 Database를 Scale-Out를 해야 되는 시스템에 적합합니다.

     

    장점

    • 스키마가 없기 때문에 유연한 데이터 구조를 가질 수 있다. 언제든 저장된 데이터를 조정하고 새로운 필드를 추가할 수 있따.
    • 데이터 분산이 용이하며 성능 향상을 위한 Saclue-up 뿐만이 아닌 Scale-out 또한 가능하다.
    • 대용량 데이터 처리에 좋음

    단점

    • 데이터 중복이 발생할 수 있으며 중복된 데이터가 변경 될 경우 수정을 모든 컬렉션에서 수행을 해야 한다.
    • 스키마가 존재하지 않기에 명확한 데이터 구조를 보장하지 않으며 데이터 구조 결정가 어려울 수 있다.

     

    - 인덱스를 사용하는 이유가 무엇일까요?                                                                                     

    1. 인덱스를 사용하는 이유

    where 구문에 해당하는 열을 빨리 찾기 위해서

    join 시 다른 테이블의 열을 빨리 추출하기 위해서

    사용가능한 키의 최 좌측 접두사(leftmst prefix)를 가지고 정렬 및 그룹화를 하기 위해서

    min() 또는 max(), count값을 찾기 위해

     

    2. 인덱스를 사용하지 않게 된다면

    서버의 Heap 영역에 데이터의 레코드들이 순서 없이 저장된다면, 특정 데이터를 찾기 위해선 Full Scan(Table Scan) 방식을 사용하게 된다. 이럴 경우 용량이 큰 테이블에서 처리 성능이 떨어질 것이다.

     

    - 인덱스의 장단점은 무엇이 있을까요?                                                                            

    1. 장점

    - 테이블의 검색 및 정렬 속도를 향상 

    - 질의나 보고서에서 그룹화 작업의 속도를 향상

    - 테이블 행의 고유성 강화

    - 필드 중에는 데이터 형식 때문에 인덱스 될 수 없는 필드도 있다.
    - 여러 필드로 이루어진(다중 필드) 인덱스를 사용하면 첫 필드 값이 같은 레코드도 구분할  수 있다.(이 때, 다중 필드 인덱스는 최대 10개 필드 포함 가능)
     

    2. 단점

    - .mdb 파일 크기가 늘어난다

    - 여러 사용자가 한 페이지에 동시에 수정할 수 있는 병행성이 줄어든다.

    - 데이터를 update, insert ,delete 시 성능 감소 ( DML에 취약함)

    - 인덱스 생성 후 데이터 변형이 계속 생성되면, 인덱스 트리의 깊이가 깊어지고, 무거워져 성능이 저하될 수 있으므로, 리밸런싱을 해야 한다.

    - 갑자기 인덱스를 추가하면 기존에 잘 돌아가고 잇던 쿼리에 옵티마이저가 실행계획을 바꾸는 경우가 생겨, 갑자기 느려질 수 있다

    (기존 테이블에 인덱스를 추가한느 경우, 기존에 있던 sql 문장들까지 전부 고려해야 한다)

     

    3. 인덱스를 생성해야 하는 경우 

    - where , join문에서 자주 사용되는 컬럼

    - 데이터의 중복도가 적은 컬럼

    - 외래키가 사용되는 열

     

    4. 인덱스를 생성하지 않아도 되는 경우 

    - 테이블 레코드 수가 작은 경우(테이블 크기가 작은 경우)

    - 인덱스가 걸린 컬럼의 유일한 값이 95%보다 적은 경우

    - DB_FILE_MULTIBLOCK_READ_COUNT 값 / 분포도 등에 따라 달라짐

    - 함수 및 연산자에 의해 자주 변경되는 경우

    - 낮은 선택도

     

    -  인덱스를 만드는 과정을 설명해보시겠어요?                                                                            

    1. 인덱스의 정의 

    인덱스란 데이터를 빠르게 검색할 수 있게 해주는 객체

    레코드 검색 시 Full Scan하는게 아닌 Index파일을 검색하여 속도를 빠르게 도움

    (반면, delete, insert, update 쿼리가 많은 경우엔 속도가 느려짐)

     

    2. 인덱스 형식 : RDBMS에서는 B+ Tree를 사용

    ( B-tree는 브랜치 노드에 key와 data를 담지만 B+ tree는 key만 담아두고, 리프 노드에만 key와 data를 저장한다. 리프 노드끼리는 linked list를 사용한다. 따라서 메모리를 더 확보함으로써 cache hit을 높일 수 있고, B+ Tree는 리프노드에 모든 데이터가 있으므로 한 번의 선형 탐색만 하면 된다.)

    ( O(1)로 접근할 수 있는 또 다른 테이블인 Hash Table을 쓰지 않는 이유는, Hash Table은 동등(=)연산에 특화 되어 있기 때문에, 적합하지 X)

     

    3. 각 쿼리 별 인덱스의 동작 방식

    1) 테이블 생성 시, 3가지 파일이 생성

      * FRM( 테이블 구조 저장 파일 )

      * MYD( 실제 데이터 파일 )

      * MYI ( Index 정보 파일 ) 

     

    2) SELECT 문 수행 시 ( name = 'turtle'인 대상 탐색 )

     * 서버 프로세스가 DB Buffer Cache에 name이 'turtle'인 정보가 있는지 확인

     * Buffer에 없다면, 하드디스크에서 turtle 정보를 가진 블록을 복 Buffer Cache로 복사한 후, 특정 데이터 출력

        ===> Index가 없는 경우, 데이터 파일 블록 전체를 Cache로 복사 후 찾음

        ===> Index가 있는 경우, where 절에 Index 컬럼이 있는지 확인 후, 인덱스에서 turtle이 어떤 'ROW ID'를 가진지 찾아서 해당 블록만 Cache에 복사 

     

    3) Insert 문 수행 시

     * 기존 Block에 여유가 없을 때, 새로운 Block을 할당 받은 후, Key를 옮긴다.

      이 때 해당 key값들은 DML이 블로킹되고, lock이 걸린다.

     

    4) Delete문 수행 시

     * Data는 삭제되어서 그 공간에 다른 Data가 사용 가능하지만, Inde는 Data는 지워지지 않고 "사용 안됨"표시만 생성

     

     5) Update 수행 시

     * Index는 Delete -> Insert 작업으로 수행한다( index에선 update가 없다.)

     

    -  클러스터형 인덱스와 넌클러스터형 인덱스를 설명해주세요                                                  

    출처 : https://gocoder.tistory.com/1826
    출처 : https://zinirun.github.io/2020/10/23/database-index/

     

    1. 클러스터 인덱스를 사용할 때

     - 레코드 추가 순서대로 필드 값이 계속 증가(감소)하는 필드

     (ex. auto increment, 날짜 )

    ( 클러스터 인덱스 필드의 순서 == 레코드의 물리적 배열 순서 이므로, 인덱스 키 값 순서대로 레코드가 자동으로 소트되어 저장된다. 위의 경우는 레코드가 추가될 때마다 물리적으로 재배치하는 작업이 적게 발생한다.)

    ( 기존 인덱스 값들보다 너무 크거나 작은 값이 멋대로 들어올 경우, Page Spliting작업이 수반된다.)

    -  equal 조건 검색보다는 range 검색이 많은 필드

    ( 클러스터 인덱스는 레코드 순서 자체가 인덱스이므로, 인덱스를 저장하기 위한 별도의 페이지를 할당할 필요가 없다. 이 말인즉, 클러스터 인덱스를 사용하는 쿼리를 실행할 경우, 인덱스가 저장된 페이지에서 쿼리 조건에 해당하는 레코드 위치 자료를 얻어내는 작업이 생략된다는 것이다. ) 

    - 일정한 범위 값에 대해 쿼리를 실행하거나, 정렬된 결과를 필요로 할 때 

    ( 이미 데이터가 인덱스 내에서 정렬되어 있기 때문)

    - 유일한 값을 가지고 레코드를 검색하는 쿼리를 사용할 때

    - Group by, Join 절 

     

    2. 넌 클러스터 인덱스를 사용할 때 

    - 반환되는 레코드의 개수가 적은 쿼리(하나의 레코드 포함)와 인덱스의 선택도가 높은 경우에(95% 이상) 

    - 가능하다면 문자보다는 정수 값을 가진 컬럼

    - 인덱스는 where 절의 가장 왼쪽 컬럼과 일치할 때만 사용된다. 

     

    -  SCAN 종류에 대해 설명해보세요                                                                         

    ###################  FULL TABLE SCAN  #######################

    1. 정의 : 테이블 전체 데이터를 읽어 조건에 맞는 데이터를 추출하는 방식

     

    2. Table Scan을 사용하는 경우

      -  조건 절에서 비교할 컬럼에 인덱스가 없는 경우

      -  조건 절에서 비교할 컬럼에 인덱스가 있지만, 해당 조건을 만족하는 데이터가 많은 비율을 차지하는 경우

      - 인덱스는 있으나, 테이블의 데이터 자체가 적은 경우

      - 테이블 생성 시 degree 속성 값이 크게 설정된 경우

     

    ###################  ROWID SCAN  #########################

    1. 정의 : ROWID를 기준으로 데이터를 추출하는 방식. 단일 행에 접근하는 방식 중  가장 빠르다.

     

    2. RowID Scan을 사용하는 경우

     - 조건절에 ROWID를 직접 명시할 경우

     - INDEX SCAN을 통해 ROWID를 추출한 후 테이블에 접근할 경우

     

    ###################   INDEX SCAN   #######################

    1. Index range scan

    -  상황 : 1. UNIQUE 성격의 결합 인덱스의 선두 컬럼이 WHERE절에 사용되는 경우
                   2. 일반 인덱스의 컬럼이 WHERE절에 존재하는 경우

    -인덱스를 통해 B+ Tree를 수직탐색 후, Leaf 블록을 필요한 범위까지 탐색하는 방식

    - < , between, IS NULL 등을 통한 범위 조건 설정 시 Index Range Scan으로 수행된다.

    - 인덱스를 구성하는 선두 컬럼이 조건절에 사용되어야 가능

     

    2. Index Range Scan Descending

    - 상황 : INDEX RANGE SCAN을 수행함과 동시에 ORDER BY DESC절을 만족하는 경우

    -인덱스 리프 블록의 양방향 링크를 이용하여 내림차순으로 데이터를 읽는 방식. 이 방식을 이용해서 최대값을 쉽게 찾을 수 있다. 

    - Index Range Scan 과 동일한 스캔 방식이나 내림차순으로 정렬된 결과집합을 얻는다는 점이 다름

     

    3. Index Full Scan

    - 상황 : 1. ORDER BY / GROUP BY의 모든 컬럼이 인덱스의 전체 또는 일부로 정의된 경우
                  2. 정렬이 필요한 명령에서 INDEX ENTRY를 순차적으로 읽는 방식으로 처리된 경우

    - 수직적 탐색 없이 인덱스  Leaf 노드들에 대해 전체 탐색하는 방식

    - 최적의 인덱스가 없을 때 차선으로 선택

    - 인덱스 선두 컬럼이 조건절에 없으면 Table Full Scan을 고려하나, Table Full Scan보다 I/O를 줄일 수 있거나 정렬된 결과를 쉽게 얻을 수 있을 경우 선택

    - count(*) 쿼리 등에 사용? 인덱스가 없을 경우 

     

    4. Index Fast Full Scan

    - 상황 : FULL TABLE SCAN을 하지 않고도 INDEX FAST FULL SCAN으로 원하는 데이터를 추출할 수 있고 추출된 데이터의 정렬이 필요 없으며 결합 인덱스를 구성하는 컬럼 중에 최소 한개 이상은 NOT NULL인 경우 

    - 인덱스 구조를 무시하고 인덱스 segment 전체를 multiblock lead 방식으로 스캔한다.

    - 즉, 물리적으로 디스크에 저장된 순서대로 인덱스 블록을 읽어 들임

    - 인덱스가 파티션 되어 있지 않더라도 병렬 쿼리 가능

    - 단점 : 인덱스 리프 노드가 갖는 연결 리스트 구조를 이용하지 않기 때문에 얻어진 결과 집합이 인덱스 키 순서대로 정렬되지 않음, 쿼리에 사용되는 모든 컬림이 인덱스 컬럼에 포함되어 있을 때만 사용 가능

     

    5. Index Unique Scan

    - 상황 : UNIQUE INDEX를 구성하는 모든 컬럼이 조건에 "="로 명시된 경우

    - 유일 인덱스를 사용하여 단 하나의 데이터를 추출하는 방식

    - 수직적 탐색만으로 데이터를 찾는 방식 

    - 쿼리 결과로 하나의 값만 반환되는 경우( primary key나 unique key로 설정된 컬럼 조건을 상수, 혹은 동등 조건으로 주었을 때) 실행

    - unique 인덱스를 통해 '=' 조건으로 탐색하는 경우

     

    6. Index Skip Scan

    - 상황 : 1. 결합 인덱스의 선행 컬럼이 WHERE절는 경우
                  2. 옵티마이저가 INDEX SKIP SCAN이 FULL TABLE SCAN보다 낫다고 판단하는 경우 

    조건절에 빠진 인덱스 선두 컬럼의 distinct value 개수가 적고 후행 컬럼의 distinct value 개수가 많을 때 유용

    루트 또는 브랜치 블록에서 읽은 컬럼 값 정보를 이용해 조건에 부합하는 레코드를 포함할 가능성이 있는 리프 블록만 골라서 액세스 하는 방식

    첫 번째 리프 블록과 마지막 리프 블록은 항상 방문

    인덱스의 전체 조건을 이용하지 않고 부분적으로 이용할 경우 사용

    /*+ index_ss(emp) */

     

    7. Index Join

    - 상황 : 추출하고자 하는 데이터가 조인하는 인덱스에 모두 포함되어 있고 추출하는 데이터의 정렬이 필요없는 경우

     

    -  인덱스가 있음에도 인덱스를 타지 않는 경우는 어떤 것이 있을지?       

    1. 인덱스 컬럼 변형

    - where 절에 사용할 인덱스에 함수를 적용한다던가 ( lower(name) == 'word', to_char(hire_date)) ,

    연산을 하는 등 ( where idx - 1 == 5 ) 의 인덱스에 변형을 가한 경우

     

    2. 내부적 데이터 변환

    - where 절에 인덱스에 딱 맞지 않는 데이터 타입을 주는 경우

    - ex) 문자열 데이터 타입 칼럼에 '값'이 아닌 값 을 적는 경우

    - where hiredate = to_date('21-01-01', 'YY/DD/DD')는 가능하지만 hire_date = '21-01-01' 은 사용 불가

     

    3. NULL 조건 혹은 NOT NULL을 사용하는 경우

    - 대부분 풀 스캔이 일어나므로, '' 혹은 0값을 직접 사용하는 것이 낫다

     

    4. NOT 또는 IN 연산자 사용

    - NOT, IN은 일반적으로 안타는 경우가 많다. NOT에 사용된 값이 아닌 데이터 비율이 높거나, IN에 포함된 데이터 비율이 높다면 FULL SCAN이 더 낫다고 판단

     

    5.  LIKE문장에서 범위를 전체 지정 시

    - %표시 가 앞쪽에 사용되면 정렬 순서를 사용할 수 없으므로 FULL SCAN이 이뤄진다.

    - where name like 'S%'는 인덱스 사용 가능

     

    6. 부정형 조건의 사용

    - where deptno != 30 -- 인덱스 사용 불가

    - where deptno < 30 or deptno > 30 -- 인덱스 사용 가능

     

    7. OR 조건 사용

    - where name = 'yaya' or name = 'ho' -- 인덱스 사용 불가능

     

    -  결합 인덱스에 대해 설명해주세요                                                                               

    - 정의 : 2개 이상의 컬럼을 합쳐서 생성한 인덱스

     

    - 사용 경우 

    1. where절에서 and 조건으로 자주 결합되어 사용되면서 각각의 분포도 보다 두 개 이상의 컬럼이 결합될 때 분포도가 좋아지는 컬럼들

    2. 다른 테이블과 조인의 연결고리로 자주 사용되는 컬럼들

    3. order by에서 자주 사용되는 컬럼들

    4. 하나 이상의 키 컬럼 조건으로 같은 테이블의 컬럼들이 자주 조회될 때

     

    - 컬럼 순서 고려 시 우선 순위

    1. where절 조건에 많이 사용되는 컬럼이 우선시

    2. Eual('=')로 사용되는 컬럼 우선

    3. 분포도가 좋은 컬럼을 우선

    4. 자주 이용되는 순서대로 결합 인덱스 컬럼의 순서 결정

     

    -  출처                                                                   

    https://coding-factory.tistory.com/744 --> 정리하기
    https://118k.tistory.com/150

    https://lalwr.blogspot.com/2016/02/db-index.html --> 정리하기

    https://jonny-cho.github.io/db/2019/11/25/sqltuning1/ -> 이것도 정리하기

    https://coding-factory.tistory.com/756?category=990785 

    https://gocoder.tistory.com/1826

    https://khj93.tistory.com/entry/Database-RDBMS%EC%99%80-NOSQL-%EC%B0%A8%EC%9D%B4%EC%A0%90

    https://owlyr.tistory.com/21

    https://blog.daum.net/creazier/15309657

    https://lalwr.blogspot.com/2016/02/db-index.html

     

     

     

     

    '전공 > DB' 카테고리의 다른 글

    MySQL튜닝3) 실행계획 살펴보기1  (0) 2022.01.19
    MySQL튜닝2) SQL 튜닝 용어 이해하기2  (0) 2022.01.12
    MySQL튜닝1) SQL 튜닝 용어 이해하기  (0) 2022.01.05
    정규화  (0) 2021.12.15
    [DB 기술면접 질문 리스트] : JOIN  (0) 2021.10.17