Table scan in RDBM
Collection scan in MongoDB
Both are a death for performance
Theory of indexing:
We keep our keys sorted.
Indexes in Mongo db are OrderedList of Keys.
Мы знаем по каким полям мы часто делаем выборку, поэтому для таких полей мы создаем индексы.
Типы идексов в Mongo:
Single Field Indexes
A single field index only includes data from a single field of the documents in a collection. MongoDB supports single field indexes on fields at the top level of a document and on fields in sub-documents.
Compound Indexes
A compound index includes more than one field of the documents in a collection.
Multikey Indexes
A multikey index references an array and records a match if a query includes any value in the array.
Geospatial Indexes and Queries
Geospatial indexes support location-based searches on data that is stored as either GeoJSON objects or legacy coordinate pairs.
Text Indexes
Text indexes supports search of string content in documents.
Hashed Index
Hashed indexes maintain entries with hashes of the values of the indexed field.
Эта отсортированная структура сохраняется на диске и по ней мы намного быстрее найдем ссылку в последовательности полных записей колекции на диске.
Например мы создаем ключ|индекс на поля
name, hear_color, age
На диск у нас сохраняется отсортированый список имен, в каждой ячейке имени хранится отсортированный список цвета волос, а в каждой ячейке цвета волос хранятся отсортированные возраста.
А уже на каждой ячейке возраста хранятся ссылки на целые записи всей колекции.
Таким образом мы можем использовать данный ключ для следующий запросов:
{name: XXX, hear_color: XXX, age: XXX}
{name: XXX, hear_color: XXX}
{name: XXX, age: XXX} по факту используется часть индексирования как для {name: XXX}
{name: XXX}
Не можем использовать данное индексирование для запросов:
{hear_color: XXX, age: XXX}
{age: XXX}
Создать индекс:
-1 - для спадающего типа индекса
Посмотреть все индексы всех колекций всех баз:
Посмотреть индексы для конкретной колекции поточной базы:
Удалить индекс:
MULTIKEY INDEXES
подобные ключи создаются когда у нас одно из указанных полей индекса может быть массивом.
То есть у нас есть разрешение учавствовать полям-массивам в индексировании, но у нас не может быть таких полей в индексе больше одного - у нас перемножается матрица, а это уже слишком много вариантов, чтобы индексировать.
Увидеть является ли какой-то ключ "мультики", мы можем в MongoDB Shell вызовом метода курсора .explain()
Ключи также могут создаваться для подполей и даже "мультики":
Мы можем также создать ограничения на индексы. Например комбинация полей должна быть уникальна:
Если мы создаем на уже заполненную колекцию индекс с указанием уникальности, есть высокая вероятность, что мы не сможем создать индекс, по той причине, что есть дубликаты.
В таком случае есть решение, которое опасное, но для определенных случаев оно сносное(удалить при созданни уникального индекса дубликаты):
"Редкие(sparse) индексы"
Эта директива позволяет создавать нам индексы для полей, которые есть не у каждом документе колекции. Если мы попробуем создать уникальный иднекс без такой директивы на поле такого типа, у нас ничего не получится, потому что все документы, которые будут без такого индекса будут считаться дубликатами, потому что у всех одно значение этого поля null.
В таком случаем мы не увидем документы, которые не содержат указанного поля.
Например такой запрос не вернет ни одного результата, потому что этот иднекс содержит только документы с указанным полем, а мы указали, что собираемся использовать редкий индекс, а не курсор:
Создание индексов в режимах Backgroud and Foreground
С версии 2.2 индексы создаются по-умолчанию в режиме бекграунд. Это означает, что Mongo Shell блокируется на время создания индексов, но в это время mongod продолжает обрабатывать запросы клиентов. Такое создание использует в 2-5 раз больше времени для создания индекса.
В режиме фореграунд mongod полностью блокирует обслуживание базы для, которой создается индекс, но индекс создается намного быстрее.
Есть также вариант более подходящий для продакшина. Если у нас есть кластер реплик, то мы одну ноду может временно изынять из класреа и создать на ней индекс в режиме фореграунд, в это время остальные будут продуктивно обслуживать запросы. А потом подключить ноду к кластеру, а индекс будет подтянут в виде копии его файла на другие ноды.
Index Selectivity - свойство индекса, которое характеризирует насколько хорошо были выбраны поля и их порядок для построения индекса, максимально уникальные поля должны идти первыми, это свойство характерно как для реляционных баз так и нет.
Index Hinting
Мы при запросах можем явно указать, какой индекс использовать - от этого может зависеть как эффективность, так и даже результата запроса(так например если мы укажем, что исвпользовать нужно спарсовый индекс, а под тело запроса нам подходит документ, который не содержит "спарсовое" поле, то у нас при этом хинтенг результат не будет найден).
Моngo по-умолчанию выбирает индекс по каким-то своим алгоритмам из созданных на колекцию. Но мы также можем указать, что не нужно использовать никакой индекс, а перебрать все поля(на самом деле используется натуральный иднекс, который создается как поле _id для всех документов).
db.people.find().sort({'title':1}).hint({$natural:1})
Конкретный идекс выглядит так:
db.people.find({'title':{$ne:null}}).hint({'title':1, 'name': 1})
Geospecial Indexes
Это вид индексов для полей, которые представлены массивом из двух елементов - 2d
Есть также тип который тоже для таких полей, но эти двухмерные координаты имеются ввиду на поверхности сферы, тоесть которые предствлены долготой и широтой - 2dsphere(Geospecial Spherical Indexes)
Фишка этих индексов в том, что при их создании мы помечаем поле для индекса не 1-й, а специальным ключевым словом:
Теперь мы можем применить специальный запрос $near, на поле такого типа:
Теперь поговорим о сферическом индексе. Mongo реализует часть спецификации geojson.org
Здесь в поле loc слова type, Point, coordinates зарезервировано-стандартизированы из формата:
Text Indexes
Для поиска в полях текста не со 100%-м соответствием.
Теперь мы можем писать запрос:
В результат подойдут следующие документы:
Collection scan in MongoDB
Both are a death for performance
Theory of indexing:
We keep our keys sorted.
Indexes in Mongo db are OrderedList of Keys.
Мы знаем по каким полям мы часто делаем выборку, поэтому для таких полей мы создаем индексы.
Типы идексов в Mongo:
Эта отсортированная структура сохраняется на диске и по ней мы намного быстрее найдем ссылку в последовательности полных записей колекции на диске.
Например мы создаем ключ|индекс на поля
name, hear_color, age
На диск у нас сохраняется отсортированый список имен, в каждой ячейке имени хранится отсортированный список цвета волос, а в каждой ячейке цвета волос хранятся отсортированные возраста.
А уже на каждой ячейке возраста хранятся ссылки на целые записи всей колекции.
Таким образом мы можем использовать данный ключ для следующий запросов:
{name: XXX, hear_color: XXX, age: XXX}
{name: XXX, hear_color: XXX}
{name: XXX, age: XXX} по факту используется часть индексирования как для {name: XXX}
{name: XXX}
Не можем использовать данное индексирование для запросов:
{hear_color: XXX, age: XXX}
{age: XXX}
Создать индекс:
db.students.ensureIndex({name: 1, hear_color: 1, age: -1})
1 - для нарастающего типа индекса-1 - для спадающего типа индекса
Посмотреть все индексы всех колекций всех баз:
db.system.indexes.find()
Посмотреть индексы для конкретной колекции поточной базы:
db.students.getIndexes()
Удалить индекс:
db.students.dropIndex({name: 1, hear_color: 1, age: 1})
MULTIKEY INDEXES
подобные ключи создаются когда у нас одно из указанных полей индекса может быть массивом.
То есть у нас есть разрешение учавствовать полям-массивам в индексировании, но у нас не может быть таких полей в индексе больше одного - у нас перемножается матрица, а это уже слишком много вариантов, чтобы индексировать.
Увидеть является ли какой-то ключ "мультики", мы можем в MongoDB Shell вызовом метода курсора .explain()
Ключи также могут создаваться для подполей и даже "мультики":
> db.peaple.find().limit(3).pretty()
{
_id: 1,
name: "Andy",
addresses: [
{
street_address: "23 Sycamore",
city: "New York",
state: "New York",
tag: "vacation"
},
{
street_address: "24 Sycamore",
city: "New York",
state: "New York",
tag: "vacation"
}
]
}
> db.people.ensureIndex({'addresses.tag':1})
Мы можем также создать ограничения на индексы. Например комбинация полей должна быть уникальна:
db.students.ensureIndex({student_id: 1, class_id: 1}, {unique: true})
После этого мы не сможет создавать документы в колекцию с повторяющимися student_id и class_id.
Если мы создаем на уже заполненную колекцию индекс с указанием уникальности, есть высокая вероятность, что мы не сможем создать индекс, по той причине, что есть дубликаты.
В таком случае есть решение, которое опасное, но для определенных случаев оно сносное(удалить при созданни уникального индекса дубликаты):
db.students.ensureIndex({student_id: 1, class_id: 1}, {unique: true, dropDups: true})
"Редкие(sparse) индексы"
Эта директива позволяет создавать нам индексы для полей, которые есть не у каждом документе колекции. Если мы попробуем создать уникальный иднекс без такой директивы на поле такого типа, у нас ничего не получится, потому что все документы, которые будут без такого индекса будут считаться дубликатами, потому что у всех одно значение этого поля null.
> db.products.ensureIndex({size:1},{unique:true, sparse:true})
> db.products.find().sort({size:1})
]
С версии 2.6 если мы сортируем по редкому полю, сортировка существуюещего индекса на нем не используется, а используется курсор по-умолчанию, поэтому мы увидем все документы колекции в предыдущем примере. Но мы можем явно указать что нужно использовать конкретный индекс а не курсор так:> db.products.find().sort({size:1}).hint({size:1})
В таком случаем мы не увидем документы, которые не содержат указанного поля.
Например такой запрос не вернет ни одного результата, потому что этот иднекс содержит только документы с указанным полем, а мы указали, что собираемся использовать редкий индекс, а не курсор:
> db.people.ensureIndex( { title : 1 } , { sparse : 1 } )
> db.people.find( { title : null } ).hint( { title : 1 } )
Создание индексов в режимах Backgroud and Foreground
В режиме фореграунд mongod полностью блокирует обслуживание базы для, которой создается индекс, но индекс создается намного быстрее.
Есть также вариант более подходящий для продакшина. Если у нас есть кластер реплик, то мы одну ноду может временно изынять из класреа и создать на ней индекс в режиме фореграунд, в это время остальные будут продуктивно обслуживать запросы. А потом подключить ноду к кластеру, а индекс будет подтянут в виде копии его файла на другие ноды.
| Regular Index | Sparse Index | Multikey Index | |
|---|---|---|---|
| Соотношение между к-вом идексов и документов в колекции | Iq == Dq | Iq <= Dq | Iq >= Dq |
Index Selectivity - свойство индекса, которое характеризирует насколько хорошо были выбраны поля и их порядок для построения индекса, максимально уникальные поля должны идти первыми, это свойство характерно как для реляционных баз так и нет.
Index Hinting
Мы при запросах можем явно указать, какой индекс использовать - от этого может зависеть как эффективность, так и даже результата запроса(так например если мы укажем, что исвпользовать нужно спарсовый индекс, а под тело запроса нам подходит документ, который не содержит "спарсовое" поле, то у нас при этом хинтенг результат не будет найден).
Моngo по-умолчанию выбирает индекс по каким-то своим алгоритмам из созданных на колекцию. Но мы также можем указать, что не нужно использовать никакой индекс, а перебрать все поля(на самом деле используется натуральный иднекс, который создается как поле _id для всех документов).
db.people.find().sort({'title':1}).hint({$natural:1})
Конкретный идекс выглядит так:
db.people.find({'title':{$ne:null}}).hint({'title':1, 'name': 1})
Geospecial Indexes
Это вид индексов для полей, которые представлены массивом из двух елементов - 2d
Есть также тип который тоже для таких полей, но эти двухмерные координаты имеются ввиду на поверхности сферы, тоесть которые предствлены долготой и широтой - 2dsphere(Geospecial Spherical Indexes)
Фишка этих индексов в том, что при их создании мы помечаем поле для индекса не 1-й, а специальным ключевым словом:
db.places.ensureIndex({location: '2d', type: 1})
Теперь мы можем применить специальный запрос $near, на поле такого типа:
db.places.find({'location': {$near: [74, 140]}}).limit(3)
Теперь поговорим о сферическом индексе. Mongo реализует часть спецификации geojson.org
db.places.ensureIndex({location: '2dsphere'})
{
"_id" : {"$oid" : "535471aaf28b4d8ee1e1c86f" },
"store_id" : 8,
"loc" : {
"type" : "Point",
"coordinates" : [ -37.47891236119904, 4.488667018711567 ]
}
}
Здесь в поле loc слова type, Point, coordinates зарезервировано-стандартизированы из формата:
db.stores.find({
loc:{
$near: {
$geometry: { type: "Point", coordinates: [-130, 39]},
$maxDistance:1000000
}
}
})
Text Indexes
Для поиска в полях текста не со 100%-м соответствием.
db.movies.ensureIndex({location: 'text'})
Теперь мы можем писать запрос:
> db.movies.find( { $text : { $search : "Big Lebowski" } } )
В результат подойдут следующие документы:
{ "title" : "The Big Lebowski" , star: "Jeff Bridges" }
{ "title" : "Big" , star : "Tom Hanks" }
{ "title" : "Big Fish" , star: "Ewan McGregor" }
Но тут есть один момент, хотелось бы получить результат отсортированным от самого подходящего к наименее подходящему. Для этого мы создадим дополнительное поле "очек", которое вставится в каждый документ результата, и по этому новодобавленному полю сделаем сортировку:> db.movies.find(
{ $text : { $search : "Big Lebowski" } },
{score: {$meta: 'textScore'}}
).sort({score: {$meta: 'textScore'}})
Комментариев нет:
Отправить комментарий