JavaRush /Курси /All lectures for UA purposes /Характеристики NoSQL баз даних

Характеристики NoSQL баз даних

All lectures for UA purposes
Рівень 1 , Лекція 635
Відкрита

1. Поява терміну NoSQL

Останнім часом термін "NoSQL" став дуже модним і популярним, активно розвиваються та просуваються всілякі програмні рішення під цією вивіскою. Синонімом NoSQL стали величезні обсяги даних, лінійна масштабованість, кластери, стійкість до відмов, нереляційність. Однак, мало хто має чітке розуміння, що ж таке NoSQL сховища, як з'явився цей термін і які загальні характеристики вони мають. Спробуємо усунути цю прогалину.

Найцікавіше в терміні, що при тому, що вперше він став використовуватись наприкінці 90-х, реальний сенс у тому вигляді, як він використовується зараз, набув лише в середині 2009. Спочатку так називалася опенсорсна база даних, створена Карло Строззі, яка зберігала всі дані, як ASCII файли і використовувала шеллівські скрипти замість SQL для доступу до даних. З "NoSQL" у його нинішньому вигляді вона нічого спільного не мала.

У червні 2009 у Сан-Франциско Йоханом Оскарссоном було організовано зустріч, на якій планувалося обговорити нові віяння на ІТ ринку зберігання та обробки даних. Головним стимулом для зустрічі стали нові опенсорсні продукти на зразок BigTable та Dynamo. Для яскравої вивіски для зустрічі потрібно було знайти ємний і лаконічний термін, який чудово вкладався б у Твіттерівський хештег. Один із таких термінів запропонував Ерік Еванс із RackSpace — «NoSQL». Термін планувався лише на одну зустріч і не мав під собою глибокого смислового навантаження, але так вийшло, що він поширився світовою мережею на кшталт вірусної реклами і став де-факто назвою цілого напряму в ІТ-індустрії. На конференції виступали Voldemort (клон Amazon Dynamo), Cassandra, Hbase (аналоги Google BigTable), Hypertable, CouchDB, MongoDB.

Варто ще раз наголосити, що термін "NoSQL" має абсолютно стихійне походження і не має загальновизнаного визначення чи наукової установи за спиною. Ця назва скоріш характеризує вектор розвитку ІТ вбік від реляційних баз даних. Розшифровується як Not Only SQL, хоча є прихильники та прямого визначення No SQL. Згрупувати та систематизувати знання про NoSQL світ спробували Прамод Садаладж та Мартін Фаулер у своїй нещодавній книзі "NoSQL Distilled".

2. Базові характеристики NoSQL баз даних

Загальних характеристик для всіх NoSQL небагато, тому що під лейблом NoSQL зараз ховається безліч різноманітних систем (мабуть, найповніший список можна знайти на сайті http://nosql-database.org/). Багато характеристик властиві лише певним NoSQL базам, це обов'язково згадаю при перерахуванні.

1. SQL не використовується

Мається на увазі ANSI SQL DML, оскільки багато баз намагаються використовувати query languages схожі на загальновідомий улюблений синтаксис, але повністю його реалізувати не вдалося нікому і навряд чи вдасться. Хоча за чутками є стартапи, які намагаються реалізувати SQL, наприклад, у хадупі (http://www.drawntoscalehq.com/ та http://www.hadapt.com/).

2. Неструктуровані (schemaless)

Сенс такий, що в NoSQL базах на відміну від реляційних структура даних не регламентована (або слабо типізована, якщо проводити аналогії з мовами програмування) — в окремому рядку або документі можна додати довільне поле без попередньої декларативної зміни структури всієї таблиці. Таким чином, якщо виникає необхідність змінити модель даних, то єдина достатня дія — відобразити зміну в коді програми.

Наприклад, при перейменуванні поля на MongoDB:


BasicDBObject order = New BasicDBObject();
order.put("date", orderDate); // Це поле було давно
order.put("totalSum", total); // Раніше ми використовували просто "sum"

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

Перший — обійти всі документи та оновити поле у всіх існуючих документах. Через обсяг даних цей процес відбувається без будь-яких блокувань (порівняний з командою alter table rename column), тому під час оновлення вже існуючі дані можуть зчитуватися іншими процесами. Тому другий варіант — перевірка в коді програми — неминуча:


BasicDBObject order = New BasicDBObject();
Double totalSum = order.getDouble("sum"); // Це стара модель
if (totalSum == null)
totalSum = order.getDouble("totalSum"); // Це оновлена модель

А вже при повторному записі ми запишемо це поле до бази в новому форматі.

Приємний наслідок відсутності схеми — ефективність роботи з розрідженими (sparse) даними. Якщо в одному документі є поле date_published, а в другому — ні, значить, ніякого порожнього поля date_published для другого створено не буде. Це, в принципі, логічно, але менш очевидний приклад — column-family бази даних NoSQL, в яких використовуються знайомі поняття таблиць/колонок. Однак через відсутність схеми, колонки не оголошуються декларативно і можуть змінюватися/додаватися під час користувальницької сесії роботи з базою. Це дозволяє, зокрема, використовувати динамічні колонки для реалізації списків.

У неструктурованої схеми є свої недоліки — окрім згаданих вище накладних витрат у коді додатка при зміні моделі даних — відсутність усіляких обмежень з боку бази (not null, unique, check constraint і т.д.) плюс виникають додаткові складності в розумінні та контролю структури даних при паралельній роботі з базою різних проєктів (відсутні будь-які словники на боці бази). Втім, в умовах сучасного світу, що швидко змінюється, така гнучкість є все ж таки перевагою. Як приклад можна навести Твіттер, який років п'ять тому разом із твіттом зберігав лише трохи додаткової інформації (час, Twitter handle та ще кілька байтів метаінформації), проте зараз на додаток до самого повідомлення в базі зберігається ще кілька кілобайт метаданих.

(Тут і далі йдеться в основному про key-value, document і column-family бази даних, graph бази даних можуть не мати цих властивостей)

3. Подання даних у вигляді агрегатів (aggregates)

На відміну від реляційної моделі, яка зберігає логічну бізнес-сутність програми в різні фізичні таблиці з метою нормалізації, NoSQL сховища оперують із цими сутностями як із цілісними об'єктами:

У цьому прикладі продемонстровано агрегати для стандартної концептуальної реляційної моделі e-commerce "замовлення — позиції замовлення — платежі — продукт". В обох випадках замовлення об'єднується з позиціями в один логічний об'єкт, при цьому кожна позиція зберігає в собі посилання на продукт і деякі його атрибути, наприклад, назва (така денормалізація необхідна, щоб не вимагати об'єкт продукту при вилученні замовлення — головне правило розподілених систем — мінімум "Джоїнів" між об'єктами). В одному агрегаті платежі об'єднані із замовленням і є складовою об'єкта, в іншому — винесені до окремого об'єкта. Цим демонструється головне правило проєктування структури даних у NoSQL базах — вона повинна підкорятися вимогам програми та бути максимально оптимізованою під найчастіші запити. Якщо платежі регулярно витягуються разом із замовленням — має сенс їх включати до загального об'єкту, якщо ж багато запитів працюють тільки з платежами — то краще їх винести в окрему сутність.

Багато хто заперечить, помітивши, що робота з великими, часто денормалізованими, об'єктами загрожує численними проблемами при спробах довільних запитів до даних, коли запити не вкладаються в структуру агрегатів. Що, якщо ми використовуємо замовлення разом з позиціями та платежами на замовлення (так працює додаток), але бізнес просить нас порахувати, скільки одиниць певного продукту було продано минулого місяця? У цьому випадку замість сканування таблиці OrderItem (у разі реляційної моделі) нам доведеться витягувати замовлення повністю в NoSQL сховище, хоча більшість цієї інформації нам буде не потрібна. На жаль, це компроміс, на який доводиться йти у розподіленій системі: ми не можемо проводити нормалізацію даних як у звичайній односерверній системі, оскільки це створить необхідність об'єднання даних з різних вузлів і може призвести до значного уповільнення роботи бази.

Плюси та мінуси обох підходів я спробував згрупувати у табличці:

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ