ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [MongoDB] Compound Index 생성해도 왜 쿼리가 느리지?
    Software Development/Database 2022. 5. 31. 20:40

    여러개의 field를 가지고 index를 생성할 때 compound index를 이용한다.

    생성한 compound index의 field를 포함하는 조건을 가지고 query를 실행해도 느린 경우가 있다.

    그 이유는 Query Selectivity과 관련이 있다.
    eplain('executionStats')로 쿼리플랜을 조회하면, totalKeysExamined, nReturned가 있다. 

    위 두 값의 차이가 크면 성능이 좋지 못한 것이다.
    예를 들어 nReturned가 100이고, totalKeysExamined가 100,000이라면 100개의 문서를 찾는데 100,000개의 키를 스캔하게 되는 것이다.

    인덱스를 타서 Collection Scan을 피하긴 했지만, 여전히 스캔하는 데이터의 양이 많은 것이다.

    100개의 문서를 반환하는데 100개의 키를 스캔하는 것이 가장 빠를 것이다.

    * MongoDB는 B-Tree Index를 사용한다.

     

    예를 들어 field A, field B, field C가 있고 각 field 마다 유니크한 값이 1,000,000, 10,000, 100라고 한다면,

    인덱스 순서를 A, B, C(1번)로 생성하는 것과 , C, B, A(2번)로 생성하는 것에 있어서 그게 차이가 난다.


    1. A, B, C로 생성하고 A에 대해서 범위 질의를 하고 B, C에 대해서 equal 질의를 한다고 했을 때, 그 범위가 30%이상이라면, A가 속한 범위 안에서 B, C를 전부 스캔을 해야하는 것이다.

    // Index Scan.
    db.sales.find({A: {'$gte': 300000}})
    
    // Index Scan.
    db.sales.find({C:5, B:500, A: {'$gte': 300000}})

     

    2. C, B, A로 생성하고 A에 대해서만 범위 질의를 한다면, collection scan이 발생하지만, C와 B에 조건이 들어간다면 얘기가 달라진다.

    // Collection Scan.
    db.sales.find({A: {'$gte': 300000}})
    
    // Index Scan.
    db.sales.find({C:5, B:500, A: {'$gte': 300000}})

    C, B로 조건을 탐색하는 비용은 범위 질의가 아니기 때문에, 비용이 1이다. 여기서 A에 대해서 범위 질의를 해도 많은 수 키가 filtering 됐기 때문에 스캔의 비용이 엄청 줄어들게 된다.

     

    인덱스가 일치하는 행의 범위를 충분히 좁히지 않으면 DB는 인덱스를 사용하여 일치하는 행 집합을 찾은 다음, 스캔하고 필터링하여 필요없는 행을 버린다.

    인덱스의 가장 중요한 목적 중 하나는 일치하는 행의 초기 후보를 최대한 좁혀 이 작업을 줄이는 것이다.

     

    이게 MongoDB의 Query Selectivity이다. 

    댓글

Designed by Tistory.