Архитектура MongoDb. Часть 1. Отличие от СУБД, обработка запросов в MongoDb

Рубрика:

NoSQL стал очень популярной темой в крупномасштабном развертывании, масштабируемость и полуструктурированные данные приводят к требованиям для баз данных, которые как раз удовлетворяет NoSQL. MongoDb – это один из продуктов  NoSQL, который впечатляет своим удобством использования и легкостью понимания ее базовой архитектуры.

Вот некоторые простые шаги для администратора, позволяющие запустить/остановить сервер MongoDb:

# Install MongoDB
mkdir /data/lib

# Start Mongod server
.../bin/mongod # data stored in /data/db

# Start the command shell
.../bin/mongo
> show dbs
> show collections

# Remove collection
> db.person.drop()

# Stop the Mongod server from shell
> use admin
> db.shutdownServer()

Существенное отличие от СУБД

MongoDb отличается от СУБД следующим образом:

  • В отличие от записи СУБД, которая является "flat" (постоянное число простого типа данных), основная единица MongoDb - "документ", который является "вложенным" и может содержать поля-мультизначения (массивы, хеш).
  • В отличие от СУБД, где все записи, хранимые в таблице, должны быть ограничены схемой таблицы, документы любой структуры могут храниться в одном хранилище.
  • В запросах нет операции  "join". В целом, данные могут быть организованными более денормализованным способом, и на разработчиков приложений ложится больше нагрузки для обеспечения непротиворечивости данных.
  • В MongoDb нет никакого понятия "транзакции". "Атомарность" гарантируется только на уровне документа (никакого частичного обновление документа произойти не может).
  • Нет понятия "изоляции", любые данные, которые считываются одним клиентом, могут быть модифицированы другим параллельным клиентом.

Путем удаления некоторых функций, которые предоставляет классическая СУБД, MongoDb стал более легким и более масштабируемым в обработке больших данных.

Обработка запросов

MongoDb принадлежит типу документо-ориентированной базы данных. В этой модели данные организованы как документ JSON и хранятся в коллекции. Коллекцию можно воспринимать как таблицу, а Документ эквивалентен записям в мире СУБД.

Вот небольшой пример:

# create a doc and save into a collection
> p = {firstname:"Dave", lastname:"Ho"}
> db.person.save(p)
> db.person.insert({firstname:"Ricky", lastname:"Ho"})

# Show all docs within a collection
> db.person.find()

# Iterate result using cursor
> var c = db.person.find()
> p1 = c.next()
> p2 = c.next()

Чтобы определить критерии поиска, должен быть предоставлен пример документа, содержащий поля, который должен соответствовать потребности.

> p3 = db.person.findone({lastname:"Ho"})

 Заметьте, что в запросе, часть значения должна быть определена прежде, чем запрос будет сделан (другими словами, он не может основываться на других атрибутах документа). Например, скажем, если у нас есть коллекция "Человек", то невозможно сформулировать запрос, который возвращают человека, вес которого в 10 раз превышает его рост.

# Return a subset of fields (ie: projection)
> db.person.find({lastname:"Ho"}, {firstname:true})

# Delete some records
> db.person.remove({firstname:"Ricky"})

Чтобы ускорить запрос, может использоваться индекс. В MongoDb индекс хранится как структура BTree (таким образом, запрос в диапазоне поддерживается автоматически). Так как сам документ - дерево, индекс может быть определен как путь и протиснуться на более глубокий уровень вложенности в документе.

# To build an index for a collection
> db.person.ensureIndex({firstname:1})

# To show all existing indexes
> db.person.getIndexes()

# To remove an index
> db.person.dropIndex({firstname:1})

# Index can be build on a path of the doc.
> db.person.ensureIndex({"address.city":1})

# A composite key can be used to build index
> db.person.ensureIndex({lastname:1, firstname:1})

Индекс может также быть создан на многозначном атрибуте, таком как массив. В этом случае у каждого элемента в массиве будет отдельный узел в BTree.

Создание индекса может быть осуществлено как в оффлайновом, так и онлайновом приоритетном режиме. Приоритетный режим обработки заданий пройдет намного быстрее, но база данных не может быть доступна в течение периода создания индекса. Если система работает в Replica Set, рекомендуется повернуть каждую задействованную базу данных оффлайн и создать индекс в приоритетном режиме.

Если в запросе несколько критериев отбора, MongoDb пытается использовать один лучший индекс, чтобы выбрать предполагаемый набор и затем последовательно выполняет итерации по ним, чтобы оценить другие критерии.

Если есть несколько индексов доступных для коллекции. При обработке запроса в первый раз, MongoDb создаст планы выполнения (по одному для каждого доступного индекса) и позволит им меняться (в течение определенного числа тиков) для выполнения, пока самый быстрый план не закончится. Будет возвращен результат самого быстрого исполнителя, а система запомнит соответствующий индекс, который он использовал. Последующий запрос будет использовать запомненный индекс, пока в коллекции не произойдет определенное число обновлений, тогда система повторяет процесс, чтобы выяснить, какой индекс является лучшим на тот момент.

Так как только один индекс будет использоваться, важно искать критерии поиска или сортировки и создавать дополнительный составной индекс, который лучше будет соответствовать запросу. Поддержание индекса не беззатратно, поскольку индекс должен обновляться, когда документы создаются, удаляются и обновляются, что перегружает операции обновления. Чтобы поддержать оптимальный баланс, мы должны периодически измерять эффективность наличия индекса (например, соотношение чтения-записи) и удалять менее эффективные индексы.

Читайте далее:

Модель хранения, обновления и транзакции в MongoDb

Модель репликации MongoDbШардинг

Map/Reduce в MongoDb

Автор: 
Ricky Ho, http://horicky.blogspot.com/2012/04/mongodb-architecture.html