14 речей, які я хотів би знати перед початком роботи з MongoDB

Переклад статті підготовлений напередодні старту курсу "Нереляційні бази даних".

14 речей, які я хотів би знати перед початком роботи з MongoDB

Основні моменти:

  • Дуже важливо розробити схему незважаючи на те, що MongoDB вона необов'язкова.
  • Аналогічно, індекси повинні відповідати вашій схемі та шаблонам доступу.
  • Уникайте використання великих об'єктів та великих масивів.
  • Будьте обережні з налаштуваннями MongoDB, особливо якщо йдеться про безпеку та надійність.
  • У MongoDB немає оптимізатора запитів, тому ви повинні бути обережні під час виконання запиту.

Я дуже давно працюю з базами даних, але нещодавно відкрив для себе MongoDB. Є кілька речей, які я хотів би знати перед початком роботи з нею. Коли в людини вже є досвід у певній сфері, у неї існують упереджені уявлення про те, що таке бази даних і що вони роблять. В надії полегшити завдання розуміння іншим, представляю список поширених помилок.

Створення сервера MongoDB без автентифікації

На жаль, MongoDB за промовчанням ставиться без автентифікації. Для робочої станції, доступом до якої встановлюється локально, така практика нормальна. Але оскільки MongoDB – це розрахована на багато користувачів система, яка любить використовувати великі обсяги пам'яті, буде краще, якщо ви поставите її на сервер з максимально можливою у ваших умовах кількістю оперативної пам'яті, навіть якщо збираєтеся використовувати її тільки для розробки. Установка на сервер через порт за замовчуванням може виявитися проблемною, особливо якщо в запиті можна виконати будь-який код на JavaScript (наприклад, $where як ідея для ін'єкції).

Є кілька методів аутентифікації, але найпростіше встановити для користувача ID/пароль. Скористайтеся цією ідеєю, поки думатимете над химерною автентифікацією на основі LDAP. Якщо говорити про безпеку, MongoDB повинна постійно оновлюватися, а логи завжди слід перевіряти на наявність несанкціонованого доступу. Мені, наприклад, подобається вибирати інший порт як порт за замовчуванням.

Не забудьте прив'язати поверхню атаки до MongoDB

Чек-лист забезпечення безпеки MongoDB містить хороші поради для зниження ризику проникнення в мережу та витоку даних. Легко відмахнутися і сказати, що сервер для розробки не потребує високого рівня безпеки. Однак все не так просто і це стосується всіх серверів MongoDB. Зокрема, якщо немає вагомої причини використовувати mapReduce, group або $ депотрібно вимкнути використання довільного коду на JavaScript, написавши у файлі конфігурації javascriptEnabled:false. Оскільки у стандартній MongoDB файли даних не зашифровані, розумно запускати MongoDB з Dedicated User, що має повний доступ до файлів, з обмеженим доступом тільки для нього та можливістю використовувати власні засоби управління доступом до файлів операційної системи.

Помилка розробки схеми

MongoDB не використовує схеми. Але це не означає, що схема не потрібна. Якщо ви хочете просто зберігати документи без будь-якої узгодженої схеми, зберігати їх можна швидко та просто, але витягти їх потім може бути страшенно складно.

Класична стаття «6 емпіричних правил для проектування схем MongoDB варто того, щоб її прочитати, а такі функції, як Провідник схем у сторонньому інструменті Studio 3T варто використовувати для регулярних перевірок схем.

Не забудьте про порядок сортування

Забувши про порядок сортування, можна найсильніше розчаруватися і втратити більше часу, ніж при використанні будь-якої іншої неправильної конфігурації. За замовчуванням MongoBD використовує бінарне сортування. Але навряд чи вона буде комусь корисною. Чутливі до регістру, наголосу, бінарні сортування вважалися цікавими анахронізмами поряд з намистами, каптанами і вусами, що завивалися ще в 80-х роках минулого століття. Тепер їх використання непростимо. У реальному житті «мотоцикл» – це те саме, що й «Мотоцикл». А «Британія» та «британія» – те саме місце. Рядкова літера – це просто великий еквівалент великої літери. І не змушуйте мене говорити про сортування діакритичних знаків. При створенні бази даних у MongoDB використовуйте параметри сортування без урахування наголосу та регістру, які відповідають мові та культурі користувачів системи. Так ви значно спростите пошук за рядковими даними.

Створення колекцій із великими документами

MongoDB рада розмістити великі документи розміром до 16 МБ у колекціях, а GridFS призначений для великих документів розміром більше 16 МБ. Але лише тому, що великі документи там можна розмістити, зберігати їх там не найкраща ідея. Найкраще MongoDB буде працювати, якщо ви зберігатимете окремі документи розміром у кілька кілобайт, розглядаючи їх більше, як рядки в широкій SQL-таблиці. Великі документи будуть джерелом проблем з продуктивністю.

Створення документів із великими масивами

Документи можуть містити масиви. Найкраще, якщо кількість елементів у масиві далека від чотиризначного числа. Якщо елементи до масиву додаються часто, він переросте документ, що містить його, і його потрібно буде переміститиотже, потрібно буде оновити та індекси. При повторній індексації документа з великим масивом, індекси часто перезаписуватимуться, оскільки під кожен елемент існує запис, що зберігає його індекс. Така переіндексація також відбувається, коли документ вставляється чи видаляється.

У MongoDB є так званий "Коефіцієнт заповнення", який надає простір для зростання документів, щоб звести цю проблему до мінімуму.
Ви можете подумати, що можна обійтися без індексації масивів. На жаль, через відсутність індексів у вас можуть виникнути інші проблеми. Оскільки документи проглядаються від початку до кінця, пошук елементів наприкінці масиву займатиме більше часу, та й більшість операцій, пов'язаних із таким документом, будуть повільними.

Не забудьте, що порядок стадій в агрегації має значення

У системі бази даних із оптимізатором запитів, запити, які ви пишете, є поясненнями того, що ви хочете отримати, а не того, як це отримати. Працює такий механізм за аналогією із замовленням у ресторані: зазвичай ви просто замовляєте страву, а не даєте докладні інструкції кухареві.

У MongoDB ви інструктуєте кухаря. Наприклад, потрібно переконатися, що дані проходять через reduce якомога раніше в пайплайні за допомогою $match и $project, а сортування відбувається лише після reduceі що пошук відбувається рівно в тому порядку, в якому вам потрібно. Наявність оптимізатора запитів, який позбавляє зайвої роботи, оптимально впорядковує етапи і вибирає тип з'єднання, може вас розпестити. У MongoDB у вас з'являється більше контролю за ціною зручності.

Такі інструменти як Студія 3Т спростять побудову запитів агрегації в MongoDB. Функція Aggregation Editor дозволить вам застосовувати оператори пайплайну по одному етапу за раз, а також перевіряти вхідні та вихідні дані на кожному етапі для спрощення дебагу.

Використання швидкого запису

Ніколи не встановлюйте параметри запису з високою швидкістю, але низькою надійністю в MongoDB. Цей режим "file-and-forget" здається швидким, оскільки команда повертається перед тим, як здійснюється запис. Якщо система впаде до того, як дані будуть записані на диск, вони загубляться і опиняться у неузгодженому стані. На щастя, у 64-бітному MongoDB включено журналування.

Двигуни для зберігання MMAPv1 та WiredTiger використовують логування для запобігання цьому, хоча WiredTiger може відновитися до останньої погодженої контрольної точки, якщо журнал вимкнено.

Журналування гарантує, що база даних знаходиться у узгодженому стані після відновлення та зберігає всі дані до моменту запису в журналі. Періодичність записів налаштовується за допомогою параметра commitIntervalMs.

Щоб бути впевненим у записах, переконайтеся, що у файлі конфігурації журнал увімкнено (storage.journal.enabled), а періодичність записів відповідає тому обсягу інформації, що ви можете дозволити собі втратити.

Сортування без індексу

При пошуку та агрегуванні часто виникає потреба у сортуванні даних. Будемо сподіватися, що це робиться на одному із заключних етапів, після фільтрації результату з метою зменшення обсягу даних, що сортуються. І навіть у такому разі для сортування вам знадобиться індекс. Можна скористатися поодиноким чи складовим індексом.

Якщо потрібного індексу немає, MongoDB обійдеться без нього. Існує обмеження пам'яті в 32 Мб на загальний розмір всіх документів операції сортування, і якщо MongoDB досягне цієї межі, вона або видасть помилку, або поверне порожній набір записів.

Пошук без підтримки індексів

Пошукові запити виконують функцію аналогічну операції JOIN у SQL. Для кращої роботи їм потрібен індекс значення ключа, що використовується як зовнішній ключ. Це неочевидно, оскільки використання не відображено у explain(). Такі індекси є доповненням до індексу, записаного в explain(), який у свою чергу використовується операторами пайплайну $match и $sortколи ті зустрічаються на початку пайплайну. Індекси тепер можуть охоплювати будь-яку стадію пайплайну агрегації.

Відмова від використання мультионовлень

метод db.collection.update() використовується для зміни частини існуючого документа або цілого документа, аж до повної заміни в залежності від заданого параметра update. Не так очевидно, що він не опрацює всі документи в колекції, доки ви не встановите параметр multi для поновлення всіх документів, що відповідають критеріям запиту.

Не забудьте про важливість порядку ключів у хеш-таблиці

В JSON об'єкт складається з невпорядкованої колекції розміром нуль або більше пар ім'я/значення, де ім'я – це рядок, а значення – це рядок, число, логічне значення, нуль, об'єкт чи масив.

На жаль, BSON надає великого значення порядку при пошуку. У MongoDB порядок ключів усередині вбудованих об'єктів має значення, Тобто { firstname: "Phil", surname: "factor" } – це не те саме, що { { surname: "factor", firstname: "Phil" }. Тобто ви повинні зберігати в документах порядок пар ім'я/значення, якщо хочете бути впевнені, що знайдете їх.

Не плутайте "Нуль" и "undefined"

значення "undefined" ніколи не було допустимим у JSON, згідно офіційним стандартом JSON (ECMA-404, Розділ 5), незважаючи на те, що воно використовується у JavaScript. Більш того, для BSON воно застаріло і перетворюється на $nullщо не завжди є гарним рішенням. Уникайте використання "undefined" у MongoDB.

Використання $limit() без $sort()

Дуже часто, коли ви ведете розробку MongoDB, корисно просто побачити зразок результату, який повернеться з запиту або агрегації. Для цього завдання вам знадобиться $limit(), але його ніколи не має бути у фінальній версії коду, якщо тільки перед ним ви не використовуєте $sort. Ця механіка потрібна, оскільки інакше ви не можете гарантувати порядок результату і не зможете надійно переглядати дані. У верхній частині результату ви отримуватимете різні записи в залежності від сортування. Для надійної роботи запити та агрегації мають бути детермінованими, тобто видавати однакові результати при кожному виконанні. Код, у якому є $limit(), але немає $sort, не буде детермінованим і згодом може викликати помилки, які буде важко відстежити.

Висновок

Єдиний спосіб розчаруватися в MongoDB – це порівнювати її безпосередньо з іншим типом баз даних, таким як СУБД, або прийти до її використання, виходячи з певних очікувань. Це все одно що порівнювати апельсин із вилкою. Системи баз даних переслідують певні цілі. Найкраще просто зрозуміти та оцінити для себе ці відмінності. Було б соромно тиснути на розробників MongoDB через шлях, який змусив їх йти шляхом СУБД. Мені хочеться бачити нові та цікаві способи вирішення старих проблем, таких як забезпечення цілісності даних та створення систем даних, стійких до збоїв та атак зловмисників.

Впровадження в MongoDB у версії 4.0 ACID transactionality — добрий приклад впровадження важливих покращень інноваційним шляхом. Мультидокументальні та мультиоператорні транзакції тепер атомарні. Також з'явилася можливість регулювати час, необхідний для отримання блокувань, і закінчувати транзакції, що зависли, а також змінювати рівень ізоляції.

14 речей, які я хотів би знати перед початком роботи з MongoDB

Читати ще:

Джерело: habr.com

Додати коментар або відгук