mongoDB 인덱스(INDEX)

이해하기 쉽고, 장황하지 않은 자료를 기반으로 강의를 진행합니다.
잔재미코딩 소식 공유
좀더 제약없이, IT 컨텐츠를 공유하고자, 자체 온라인 강의 사이트와 유투브 채널을 오픈하였습니다
응원해주시면, 곧 좋은 컨텐츠를 만들어서 공유하겠습니다
●  잔재미코딩 유투브 오픈 [구독해보기]

8. mongoDB 인덱스(INDEX)

  • https://docs.mongodb.com/manual/indexes/
  • SQL index와 개념적으로 동일
  • 즉, 검색을 더 빠르게 수행하고자 만드는 추가적인 data structure
    • index가 없으면 collection scan (컬렉션의 데이터를 하나하나 조회하는 방식) 으로 검색을 하게 됨
  • Document의 필드들에 index 를 걸면, 데이터의 설정한 키 값을 가지고 document들을 가리키는 포인터 값으로 이뤄진 B-Tree 데이터 구조를 만듬
    • B-Tree : Balanced Binary search Tree, Binary Search (이진 검색) 으로 쿼리 속도를 검색 속도 개선

8.1. 기본 인덱스 _id

  • 모든 MongoDB의 컬렉션은 기본적으로 _id 필드에 인덱스가 존재
  • mongodb는 _id 를 기반으로 기본 인덱스 생성

8.2. Single(단일) 필드 인덱스

  • _id 인덱스 외에도, 사용자가 지정 할 수 있는 단일 필드 인덱스
  • 기본 사용 문법(mongodb CLI): db.COLLECTION.createIndex( { 'field': 1 } ) 또는 db.COLLECTION.createIndex( { 'field': -1 } )
    • 키의 값에는 1, -1 둘중의 하나가 올 수 있음
    • 1 : 순방향(ASCENDING), -1 : 역방향(DESCENDING)

8.3. Compound (복합) 필드 인덱스

  • 두개 이상의 필드를 사용하는 인덱스를 복합 인덱스라고 부름
  • 기본 사용 문법(mongodb CLI): db.COLLECTION.createIndex( { 'field1': 1, 'field2': -1} )
  • 인덱스 방향이 성능에 영향을 미침
    • createIndex({a : 1, b : -1})로 생성한 경우
    • db.x.find({a : 1, b : -1}), db.x.find({a : -1, b : 1}) 의 쿼리만 효과를 봄
    • db.x.find({a : 1, b : 1}), db.x.find({a : -1, b : -1}) 의 쿼리는 효과 없음
  • 복합 인덱스의 경우 필드의 개수가 31개를 넘을 수 없음

8.4. Text 인덱스

  • 텍스트 관련 데이터를 효율적으로 쿼리하기 위한 인덱스
  • 기본 사용 문법(mongodb CLI): db.COLLECTION.createIndex( { 'field' : 'text' } )
본 자료와 같이 IT 기술을 잘 정리하여, 온라인 강의로 제공하고 있습니다
체계적으로 전문가 레벨까지 익힐 수 있도록 온라인 강의 로드맵을 제공합니다

pymongo에서는 create_index() 메서드를 제공함

8.5. 코드로 작성해보면서 이해하는 인덱스

In [2]:
import pymongo
In [3]:
username = 'davelee'
password = 'korea123'
connection = pymongo.MongoClient('mongodb://%s:%s@www.funcoding.xyz' % (username, password))
db = connection.test_index_db
In [6]:
# test_index_db 에는 어떤 컬렉션이 있을까?
db.collection_names()
Out[6]:
['articles']
본 자료와 같이 IT 기술을 잘 정리하여, 온라인 강의로 제공하고 있습니다
가장 빠르게 풀스택 개발자가 될 수 있도록, 최적화된 로드맵을 제공합니다
In [10]:
# test data 삽입
db.articles.insert_many(
    [
        { "name": "Java Hut", "description": "Coffee and cakes", "ranking": 1 },
        { "name": "Burger Buns", "description": "Java hamburgers", "ranking": 2 },
        { "name": "Coffee Shop", "description": "Just coffee", "ranking": 3 },
        { "name": "Clothes Clothes Clothes", "description": "Discount clothing", "ranking": 4 },
        { "name": "Java Shopping", "description": "Indonesian goods", "ranking": 5 }
    ]
)
Out[10]:
<pymongo.results.InsertManyResult at 0x1069a1e48>
In [9]:
db.articles.drop()

8.6. Single(단일) 필드 인덱스 생성 with pymongo

In [11]:
# text 인덱스 생성 
db.articles.create_index('ranking')
Out[11]:
'ranking_1'
In [12]:
# text 인덱스 확인
db.articles.index_information()
Out[12]:
{'_id_': {'key': [('_id', 1)], 'ns': 'test_index_db.articles', 'v': 2},
 'ranking_1': {'key': [('ranking', 1)],
  'ns': 'test_index_db.articles',
  'v': 2}}
본 자료와 같이 IT 기술을 잘 정리하여, 온라인 강의로 제공하고 있습니다
체계적으로 전문가 레벨까지 익힐 수 있도록 온라인 강의 로드맵을 제공합니다
  • "key" which is a list of (key, direction) pairs specifying the index (as passed to create_index()).
  • _id 는 기본 인덱스로 설정, 1 은 pymongo.ASCENDING
  • subject 는 create_index() 로 만들어진 인덱스
    • 키의 1, -1, 'text' 알아보기
      • pymongo.ASCENDING = 1
      • pymongo.DESCENDING = -1
      • pymongo.TEXT = 'text'

8.7. 특정 인덱스 삭제 with pymongo

In [13]:
# index_information() 에 넣어진 'key'의 값을 통째로 정확하게 적어야 삭제 가능
db.articles.drop_index([('ranking', 1)])
In [14]:
# text 인덱스 다시 생성 
db.articles.create_index([('ranking', pymongo.DESCENDING)])
db.articles.index_information()
Out[14]:
{'_id_': {'key': [('_id', 1)], 'ns': 'test_index_db.articles', 'v': 2},
 'ranking_-1': {'key': [('ranking', -1)],
  'ns': 'test_index_db.articles',
  'v': 2}}

8.8. 전체 인덱스 삭제 with pymongo

본 자료와 같이 IT 기술을 잘 정리하여, 온라인 강의로 제공하고 있습니다
가장 빠르게 풀스택 개발자가 될 수 있도록, 최적화된 로드맵을 제공합니다
In [15]:
# index_information() 에 넣어진 'key'의 값을 통째로 정확하게 적어야 삭제 가능
db.articles.drop_indexes()
In [16]:
db.articles.index_information()
Out[16]:
{'_id_': {'key': [('_id', 1)], 'ns': 'test_index_db.articles', 'v': 2}}

8.9. Text 인덱스 생성 with pymongo

In [17]:
db.articles.create_index([('name', pymongo.TEXT)])
Out[17]:
'name_text'
In [18]:
db.articles.index_information()
Out[18]:
{'_id_': {'key': [('_id', 1)], 'ns': 'test_index_db.articles', 'v': 2},
 'name_text': {'default_language': 'english',
  'key': [('_fts', 'text'), ('_ftsx', 1)],
  'language_override': 'language',
  'ns': 'test_index_db.articles',
  'textIndexVersion': 3,
  'v': 2,
  'weights': SON([('name', 1)])}}
본 자료와 같이 IT 기술을 잘 정리하여, 온라인 강의로 제공하고 있습니다
체계적으로 전문가 레벨까지 익힐 수 있도록 온라인 강의 로드맵을 제공합니다
In [19]:
db.articles.drop_indexes()

8.10. Compound (복합) 필드 인덱스 생성 with pymongo

In [20]:
db.articles.create_index([('name', pymongo.TEXT), ('ranking', pymongo.ASCENDING)])
Out[20]:
'name_text_ranking_1'
In [21]:
db.articles.index_information()
Out[21]:
{'_id_': {'key': [('_id', 1)], 'ns': 'test_index_db.articles', 'v': 2},
 'name_text_ranking_1': {'default_language': 'english',
  'key': [('_fts', 'text'), ('_ftsx', 1), ('ranking', 1)],
  'language_override': 'language',
  'ns': 'test_index_db.articles',
  'textIndexVersion': 3,
  'v': 2,
  'weights': SON([('name', 1)])}}
  • name_text_ranking_1 : 복합 인덱스는 복합 컬럼으로 검색할 경우에만 의미가 있고, 검색 형태에 따라 성능 개선의 효과가 있을 수도/없을 수도 있음
    • createIndex({a : 1, b : -1})로 생성한 경우
      • db.x.find({a : 1, b : -1}), db.x.find({a : -1, b : 1}) 의 쿼리만 효과를 봄
      • db.x.find({a : 1, b : 1}), db.x.find({a : -1, b : -1}) 의 쿼리는 효과 없음
본 자료와 같이 IT 기술을 잘 정리하여, 온라인 강의로 제공하고 있습니다
가장 빠르게 풀스택 개발자가 될 수 있도록, 최적화된 로드맵을 제공합니다
In [22]:
db.articles.drop_indexes()

8.11. Text 인덱스와 검색 with pymongo

In [23]:
db.articles.create_index([('name', pymongo.TEXT)])
Out[23]:
'name_text'
In [24]:
result = db.articles.find()
for record in result:
    print(record)
{'_id': ObjectId('5a0c189581f640052dfee6b0'), 'name': 'Java Hut', 'description': 'Coffee and cakes', 'ranking': 1}
{'_id': ObjectId('5a0c189581f640052dfee6b1'), 'name': 'Burger Buns', 'description': 'Java hamburgers', 'ranking': 2}
{'_id': ObjectId('5a0c189581f640052dfee6b2'), 'name': 'Coffee Shop', 'description': 'Just coffee', 'ranking': 3}
{'_id': ObjectId('5a0c189581f640052dfee6b3'), 'name': 'Clothes Clothes Clothes', 'description': 'Discount clothing', 'ranking': 4}
{'_id': ObjectId('5a0c189581f640052dfee6b4'), 'name': 'Java Shopping', 'description': 'Indonesian goods', 'ranking': 5}
In [25]:
# $text operator를 사용한 인덱스 텍스트 데이터 검색 ($text operator 는 $search operator 와 함께 사용됨)
result = db.articles.find({'$text' : {'$search' : 'coffee'}})
for record in result:
    print(record)
{'_id': ObjectId('5a0c189581f640052dfee6b2'), 'name': 'Coffee Shop', 'description': 'Just coffee', 'ranking': 3}
본 자료와 같이 IT 기술을 잘 정리하여, 온라인 강의로 제공하고 있습니다
체계적으로 전문가 레벨까지 익힐 수 있도록 온라인 강의 로드맵을 제공합니다
In [26]:
# 띄어쓰기가 있는 경우
result = db.articles.find({'$text' : {'$search' : 'java coffee shop'}})
for record in result:
    print(record)
{'_id': ObjectId('5a0c189581f640052dfee6b0'), 'name': 'Java Hut', 'description': 'Coffee and cakes', 'ranking': 1}
{'_id': ObjectId('5a0c189581f640052dfee6b4'), 'name': 'Java Shopping', 'description': 'Indonesian goods', 'ranking': 5}
{'_id': ObjectId('5a0c189581f640052dfee6b2'), 'name': 'Coffee Shop', 'description': 'Just coffee', 'ranking': 3}
In [27]:
# coffee shop 으로 정확한 검색
result = db.articles.find({'$text': {'$search':"\"coffee shop\"" } } )
for record in result:
    print(record)
{'_id': ObjectId('5a0c189581f640052dfee6b2'), 'name': 'Coffee Shop', 'description': 'Just coffee', 'ranking': 3}
In [28]:
# 대소문자 구별 (실제 name의 컬럼값은 Coffee 이므로, 검색이 안됨)
result = db.articles.find({'$text' : {'$search' : 'coffee', '$caseSensitive' : True}})
for record in result:
    print(record)
In [31]:
# 정규표현식 ($text operator 는 $search operator 와 함께 사용됨)
result = db.articles.find({'name' : {'$regex' : 'Cof.+'}})
for record in result:
    print(record)
{'_id': ObjectId('5a0c189581f640052dfee6b2'), 'name': 'Coffee Shop', 'description': 'Just coffee', 'ranking': 3}
In [30]:
# 정규표현식, 실제 컬럼명과 함께 사용 가능 ($text operator 는 $search operator 와 함께 사용됨)
result = db.articles.find({'name' : {'$regex' : 'Cof.+'}})
for record in result:
    print(record)
{'_id': ObjectId('5a0c189581f640052dfee6b2'), 'name': 'Coffee Shop', 'description': 'Just coffee', 'ranking': 3}