Архитектурный Недостаток В Couchdb

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

Одной из таких проблем является удаление записей в базе данных.

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

Хитрость в том, что это неправда.

И если с реляционными базами данных это верно лишь частично, то с NoSQL это может быть полной ложью.

Это проблема, о которой мы поговорим далее в Apache CouchDB. Картинка по теме:

Архитектурный недостаток в CouchDB



Как хранятся данные

Данные в любой базе данных хранятся по принципу файловой системы: есть карта размещения данных и файл, в котором они непосредственно находятся.

Для SQL это обычно таблица, а для NoSQL — дерево.

Когда мы удаляем данные, как в случае с файловой системой, база данных не будет тратить время на воссоздание файла карты и файла данных без записи, которую мы хотим удалить.

Он просто отметит запись на карте как удаленную.

Это легко проверить; для этого создадим простую таблицу в MySQL с помощью MyISAM, добавим туда одну запись, затем удалим ее и посмотрим статистику:

Архитектурный недостаток в CouchDB

Чтобы оптимизировать это, нам нужно воссоздать файл карты и файл данных.

Давай сделаем:

OPTIMIZE TABLE guest;

и мы получаем:

Архитектурный недостаток в CouchDB

Интересно, что таблица в неоптимизированной версии, как ни странно, работает почти так же быстро, как и в оптимизированной.

Происходит это потому, что сам принцип хранения реляционных данных обычно довольно прост и легко подсчитать, какой объем поиска нужно сделать, чтобы пропустить удаленные записи.

Сказанное, конечно, не означает, что накладные расходы можно игнорировать, но достаточно написать простой bash-скрипт, который будет оптимизировать данные по расписанию, и никакой дополнительной работы в программном коде делать не придется.

Следует отметить, что вышесказанное не совсем подходит для InnoDB, где нюансов еще больше, но сегодня статья о CouchDB, а не о MySQL.


Как работает удаление в CouchDB

Возьмем простой документ:

Архитектурный недостаток в CouchDB

и удалите его.

Что происходит? База данных помечает документ как удаленный.

Как она это делает? Он читает документ, удаляет из него все поля, вставляет дополнительное свойство _deleted: правда и записывает документ в новой редакции.

Пример:

Архитектурный недостаток в CouchDB

Теперь, если вы попытаетесь получить последнюю версию документа, вы получите ошибку 404, указывающую, что документ был удален.

Однако если вы обратитесь к первой редакции документа, она будет доступна.

Далее мы делаем компактный .

Для удаленных документов база данных автоматически удалит все версии, кроме той, которая указывает на то, что документ был удален.

Это сделано для того, чтобы сообщить об этом другой базе данных во время репликации.

Эта ревизия остается в базе данных навсегда и не может быть удалена.

(Это правда, что вы можете использовать _purge, но это костыль с множеством негативных эффектов, и его не рекомендуется использовать в производстве.

)

Как это влияет на работу?

В CouchDB данные хранятся в виде B+ дерево .

Удаленный документ, даже если он является фиктивным, остается частью дерева.

Это означает, что эта мертвая запись принята во внимание.

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



Контроль над головой

Наконец, еще неизвестно, насколько быстр Erlang. Теперь, если вы возьмете синтетические тесты , то вы увидите, что производительность Эrlang близка к PHP. То есть дерево B+ не управляется самым быстрым языком.



Как это замедляется в реальности?

Если WRITE для вас не самая редкая операция, то, имея в дереве несколько миллионов документов, вы неожиданно (и именно неожиданно) можете обнаружить, что база данных начинает сильно тормозить.

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

Возьмем график из реального производства:

Архитектурный недостаток в CouchDB

На графике видно, что пики довольно резкие.

Резкое увеличение пика не всегда предсказуемо.

Иногда у нас бывает около 2 миллионов обновлений базы (около 1 миллиона документов в дереве) и это работает вполне хорошо, но появляются еще 100 тысяч, и производительность уходит в пропасть.

А резкий спад пика происходит потому, что мы перестраиваем базу и производительность становится приемлемой на несколько недель.



выводы

  • CouchDB хранит все документы в дереве B+, которое периодически перестраивается.

    Эрланг не самый быстрый язык для этого.

    Не используйте CouchDB для документов с коротким сроком жизни, иначе вы получите слишком большое дерево, поскольку документы из него никогда не удаляются.

  • Даже если вы не удалите документы, у вас возникнут задержки при добавлении новых, если у вас есть несколько миллионов записей.

  • Советую обратить внимание на статью 16 практических советов по работе с CouchDB .

  • Становится понятно, почему Дэмиен Кац, создатель CouchDB, решил создать форк CouchBase и переписать ядро на C .

    Кстати, CouchBase содержит встроенный memcached, который позволяет хранить в отдельной области документы с небольшим сроком жизни.

Теги: #NoSQL #CouchDB #b-tree #NoSQL
Вместе с данным постом часто просматривают: