Первоначально Написал Стефан Комбоудон
Отсутствие схемы — одна из ключевых особенностей MongoDB. С другой стороны, это позволяет разработчикам легко изменять схему своих коллекций, не дожидаясь готовности базы данных принять новую схему. Однако схема не является бесплатной, и одним из недостатков является усиление записи. Давайте сосредоточимся на этой теме.
Напишите усиление?
Связь между схемой и усилением записи не очевидна с первого взгляда. Итак, давайте сначала посмотрим на таблицу в реляционном мире:
mysql> SELECT * FROM user LIMIT 2;
+----+-------+------------+-----------+-----------+----------------------------------+---------+-----------------------------------+------------+------------+
| id | login | first_name | last_name | city | country | zipcode | address | password | birth_year |
+----+-------+------------+-----------+-----------+----------------------------------+---------+-----------------------------------+------------+------------+
| 1 | arcu | Vernon | Chloe | Paulista | Cook Islands | 28529 | P.O. Box 369, 1464 Ac Rd. | SSC44GZL5R | 1970 |
| 2 | quis | Rogan | Lewis | Nashville | Saint Vincent and The Grenadines | H3T 3S6 | P.O. Box 636, 5236 Elementum, Av. | TSY29YRN6R | 1983 |
+----+-------+------------+-----------+-----------+----------------------------------+---------+-----------------------------------+------------+------------+
Поскольку все записи имеют одинаковые поля, имена полей хранятся один раз в отдельном файле (файл .frm). Таким образом, имена полей — это метаданные, а значение каждого поля для каждой записи — это, конечно, данные.
Теперь давайте посмотрим на эквивалентную коллекцию в MongoDB:
{
{
"login": "arcu",
"first_name": "Vernon",
"last_name": "Chloe",
"city": "Paulista",
"country": "Cook Islands",
"zipcode": "28529",
"address": "P.O. Box 369, 1464 Ac Rd.",
"password": "SSC44GZL5R",
"birth_year": 1970
},
{
"login": "quis",
"first_name": "Rogan",
"last_name": "Lewis",
"city": "Nashville",
"country": "Saint Vincent and The Grenadines",
"zipcode": "H3T 3S6",
"address": "P.O. Box 636, 5236 Elementum, Av.",
"password": "TSY29YRN6R",
"birth_year": 1983
}
}
Одно отличие от таблицы в реляционном мире состоит в том, что MongoDB не знает, какие поля будут в каждом документе. Поэтому имена полей — это данные, а не метаданные, и они должны храниться вместе с каждым документом.
Тогда возникает вопрос: насколько велика нагрузка на дисковое пространство? Чтобы иметь представление, я вставил 10M таких записей в таблицу InnoDB (добавив индекс по паролю и на birth_year, чтобы таблица выглядела как настоящая таблица): размер на диске составляет около 1,4 ГБ .
Я также вставил те же 10M записей в коллекцию MongoDB, используя обычный механизм хранения MMAPv1, снова добавив индекс по паролю и birth_year, и на этот раз размер на диске… 2.97 ГБ !
Конечно, это не сравнение яблок и яблок, поскольку формат хранения InnoDB и формат хранения MongoDB не идентичны. Однако разница в 100% все еще значительна.
компрессия
Один из способов справиться с усилением записи — использовать сжатие. В MongoDB 3.0 доступен механизм хранения WiredTiger, одним из преимуществ которого является сжатие (алгоритм по умолчанию: snappy ). Percona TokuMX также имеет встроенное сжатие с использованием zlib по умолчанию.
Перестройка коллекции с 10M документами и двумя индексами теперь дает следующие результаты:
WiredTiger: 1.14GB
TokuMX: 736MB
Это сокращение размера данных в 2,5-4 раза, очень хорошо!
WiredTiger также обеспечивает сжатие zlib, и в этом случае сбор составляет всего 691 МБ . Однако загрузка ЦП намного выше по сравнению с snappy, поэтому zlib можно использовать не во всех ситуациях.
Вывод
Конструкция без схемы в MongoDB привлекательна, но имеет несколько компромиссов. Усиление записи является одним из них, и использование WiredTiger с MongoDB 3.0 или Percona TokuMX является очень простым способом решения этой проблемы.