Сприяння незмінності в дизайні баз даних


26

Один із пунктів Ефективної Java Джошуа Блоха - це поняття про те, що класи повинні дозволяти мутації екземплярів якнайменше, а краще взагалі.

Часто дані об'єкта зберігаються у базі даних певної форми. Це спонукало мене до думки про ідею незмінності в базі даних, особливо для тих таблиць, які представляють собою єдину сутність у більшій системі.

Щось я нещодавно експериментував - це ідея намагатися мінімізувати оновлення, які я роблю, до рядків таблиці, що представляють ці об’єкти, і намагатися виконувати вставки настільки, наскільки я можу.

Конкретний приклад того, з чим я нещодавно експериментував. Якщо я знаю, що згодом я можу додати запис із додатковими даними, я створю ще одну таблицю для представлення цього типу, як-от наступні два визначення таблиці:

create table myObj (id integer, ...other_data... not null);
create table myObjSuppliment (id integer, myObjId integer, ...more_data... not null);

Сподіваємось, очевидно, що ці імена не є дослівними, а просто для демонстрації ідеї.

Це розумний підхід до моделювання стійкості даних? Чи варто намагатися обмежити оновлення, які виконуються в таблиці, особливо для заповнення нулів для даних, які можуть не існувати, коли запис створений спочатку? Чи бувають випадки, коли такий підхід може згодом викликати сильний біль?


7
Я відчуваю, що це рішення без проблем ... Вам слід оновлювати, а не створювати складні адаптації, щоб уникнути оновлення.
Фоско

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

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

6
Я думаю, що є вагомий аргумент щодо незмінності в базах даних. Це вирішує масу проблем. Я думаю, що негативні коментарі не надійшли від відкритих людей. Поточні оновлення є причиною багатьох проблем. Я б заперечував, що у нас все це відстало. Поточні оновлення - це застаріле рішення проблеми, яка вже не існує. Зберігання дешеве. Навіщо це робити? Скільки систем БД мають журнали аудиту, системи версій, потребує розподіленої реплікації, яка, як ми всі знаємо, вимагає можливості підтримувати затримку для масштабу. Незмінюваність вирішує все це.
цир

@Fosco Деякі системи абсолютно зобов'язані ніколи не видаляти дані (в тому числі використовувати UPDATE). Як і медичні записи лікаря.
Ізката

Відповіді:


25

Основна мета непорушності - забезпечити відсутність моменту, коли дані в пам'яті знаходяться в недійсному стані. (Інше полягає в тому, що математичні позначення здебільшого статичні, і тому незмінні речі легше концептуалізувати та моделювати математично.) У пам'яті, якщо інший потік намагається читати чи записувати дані під час роботи, він може закінчитися пошкодженням, або сама може бути в корумпованому стані. Якщо у вас кілька операцій з призначенням полів об’єкта, у багатопотоковому додатку інший потік може спробувати працювати з ним десь між ними, що може бути поганим.

Незмінність виправляє це, спочатку записуючи всі зміни на нове місце в пам’яті, а потім виконуючи остаточне завдання як один крок кроком переписування покажчика на об’єкт, щоб вказати на новий об’єкт - що на всіх процесорах є атомним операція.

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

Це також те саме, що і ваша ідея створення нових таблиць, за винятком більш автоматичних та гнучкіших.

Отже, щоб відповісти на ваше запитання, так, незмінність добре в базах даних, але ні, вам не потрібно складати окремі таблиці саме для цієї мети; ви можете просто використовувати будь-які команди атомних транзакцій, доступні для вашої системи баз даних.


Дякую за відповідь. Ця перспектива була саме тим, що мені потрібно було зрозуміти, що моя інтуїція заплутано намагалася поєднати пару різних ідей в єдиний зразок.
Ед Каррел

8
Тут є трохи більше, ніж атмосфера. Аргумент, який я бачу найчастіше на користь непорушності в контексті ООП, полягає в тому, що незмінні об'єкти вимагають лише підтвердження їх стану в конструкторі. Якщо вони є змінними, тоді кожен метод, який може змінити свій стан, також повинен перевірити, що отриманий стан все ще є дійсним, що може додавати класу значну складність. Цей аргумент потенційно застосовується і до баз даних, але набагато слабший, оскільки правила перевірки db мають тенденцію бути декларативними, а не процедурними, тому їх не потрібно дублювати для кожного запиту.
Дейв Шерохман

24

Це залежить від того, яку користь ви очікуєте від непорушності. Відповідь Рей Міясаки стосувалася одного (уникнення недійсних проміжних станів), але ось інше.

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

Це, ймовірно, відображається у світі баз даних найчастіше як тимчасові дані. Скажіть, минулого місяця ви були на базовому плані, але 16-го ви перейшли на план преміум-класу. Якщо ми просто перекреслимо поле, яке вказувало, на якому плані ви працюєте, у нас можуть виникнути труднощі з правильним виставленням рахунків. Ми також можемо пропустити можливість аналізу тенденцій. (Гей, подивіться, що зробила ця місцева рекламна кампанія!)

Ось що мені спадає на думку, коли ви кажете "незмінність у дизайні бази даних".


2
Я не згоден з вашим третім пунктом. Якщо ви хочете мати історію (журнал аудиту, журнал змін плану тощо), для цього потрібно створити окрему таблицю. Дублювання всіх 50 полів Customerтаблиці, тільки щоб пам’ятати, що користувач змінив план, не приносить нічого, крім величезного недоліку продуктивності, повільнішого вибору з часом, складнішого вилучення даних (порівняно з журналами) та більше витраченого простору.
Арсеній Муренко

6
@MainMa: можливо, я повинен був просто сказати "перейти читати про тимчасові бази даних". Мій приклад був задуманий як ескіз того, що таке часові дані; Я не стверджую, що це завжди найкращий спосіб представити зміни даних. З іншого боку, хоча підтримка тимчасових даних в даний час є досить поганою, я очікую, що тенденція спрямована на розміщення тимчасових даних у самій базі даних, а не на відновлення їх до представлень "другого класу", таких як журнали змін.
Райан Калпеппер

Що робити, якщо ми зберігаємо історію змін у таблиці аудиту (весняне завантаження та сплячий режим, наприклад, порушують цю можливість)?
Мохаммед Наджар

14

Якщо вас цікавлять переваги, які ви можете отримати від незмінності в базі даних або, принаймні, в базі даних, яка пропонує ілюзію незмінності, перевірте Datomic.

Datomic - це база даних, придумана Річком Хікі в союзі з Think Relevant. Є багато відео, де вони пояснюють архітектуру, цілі, модель даних. Пошук infoq, один зокрема має назву Датомічний, база даних як цінність . У конференціях ви можете знайти основну інформацію, яку Річ Хікі дав на конференції euroclojure в 2012 році. Confreaks.com/videos/2077-euroclojure2012-day-2-keynote-the-datomic-architecture-and-data-model

Існує розмова на vimeo.com/53162418, яка більше орієнтована на розвиток.

Ось ще один із stuart halloway at.pscdn.net/008/00102/videoplatform/kv/121105techconf_close.html

  • Datomic - це база даних фактів у часі, званих датами, у 5-х кортежах [E, A, V, T, O]
    • E Ідентифікатор об'єкта
    • Ім'я атрибута по суті (може мати простір імен)
    • V Значення атрибута
    • T Ідентифікатор транзакції, з цим у вас є поняття про час.
    • O одна операція твердження (теперішнє або поточне значення), відхилення (минуле значення);
  • Використовує власний формат даних, який називається EDN (розширювана нотація даних)
  • Операції є кислотними
  • Використовує журнал даних як мову запитів, який є декларативним як SQL + рекурсивні запити. Запити представлені структурами даних, а розширені мовою jvm, вам не потрібно використовувати clojure.
  • База даних відокремлена в трьох окремих службах (процесах, машинах):
    • Угода
    • Зберігання
    • Запит двигуна.
  • Ви можете окремо масштабувати кожну послугу.
  • Це не з відкритим кодом, але є безкоштовна (як у пиві) версія Datomic.
  • Ви можете вказати гнучку схему.
    • набір атрибутів відкритий
    • будь-коли додайте нові атрибути
    • відсутність жорсткості у визначенні чи запиті

Тепер, оскільки інформація зберігається як факти у часі:

  • все, що ви робите, - це додавати факти до бази даних, ви ніколи не видаляєте їх (за винятком випадків, коли цього вимагає закон)
  • ви можете кешувати все назавжди. Query Engine, працює на сервері додатків як у базі даних пам'яті (для мов jvm, які не є jvm, мають доступ через API REST.)
  • ви можете запитувати як раніше.

База даних є значенням і параметром для механізму запитів, QE управляє з'єднанням і кешуванням. Оскільки ви можете бачити db як значення і незмінну структуру даних у пам'яті, ви можете об'єднати його з іншою структурою даних, виготовленою зі значень "у майбутньому" і передавати її QE & запиту майбутніми значеннями, не змінюючи фактичну базу даних .

Є проект з відкритим кодом від Rich Hickey, який називається codeq , ви можете знайти його в github Datomic / codeq, який розширює модель git, а також зберігає посилання на об’єкти git у базі даних, що не містять датомів, і запитує ваш код, ви можна побачити приклад використання датомічного.

Ви можете думати про датомік як про ACID NoSQL, за допомогою даних можна моделювати таблиці або документи або Kv-магазини або графіки.


7

Ідея уникати оновлень та віддавати перевагу вставкам - одна з думок, що створюють сховище даних як джерела події, ідею, яку ви часто знайдете, використовуючи разом із CQRS. У моделі джерела подій оновлення не відбувається: сукупність представлена ​​як послідовність її "перетворення" (подій), і в результаті зберігання додається лише для додавання.
Цей сайт містить цікаві дискусії про CQRS та пошук подій, якщо вам цікаво!


Цього дня наголошується CQRS та події.
Гульшань

6

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

Основна конструкція:

  1. Завжди використовуйте згенерований сурогатний ключ як основний ключ.
  2. Унікальний ідентифікатор того, що ви описуєте, стає "логічним ключем".
  3. Кожен рядок повинен мати принаймні часову позначку "ValidFrom" та, за бажанням, часову позначку "ValidTo" та ще більше, додатково, прапор "Остання версія".
  4. Під час "створення" логічного об'єкта Ви вставляєте новий рядок із "Дійсною" від поточної часової позначки. Необов’язковий ValidTo встановлено на "вічно" (9999-12-31 23:59:59), а останню версію - на "Істинно".
  5. Про подальше оновлення логічної сутності. Ви принаймні вставите новий рядок, як зазначено вище. Вам також може знадобитися відрегулювати ValidTo для попередньої версії на "зараз () - 1 секунда", а останню версію - на "Невірно"
    1. При логічному видаленні (це працює лише з часовою позначкою ValidTo!) Ви встановлюєте прапор ValidTo у поточному рядку на "зараз () -1 секунда".

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

Недоліки полягають у тому, що ви зберігаєте набагато більше даних, і вам потрібно підтримувати більше індексів (принаймні, на Logical Key + ValidFrom + ValidTo). Індекс на логічному ключі + остання версія значно прискорює більшість запитів. Це також ускладнює ваш SQL!

Чи варто це робити, якщо вам справді не потрібно підтримувати історію та не вимагаєте відтворити стан ваших організацій у певний момент часу?


1

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


0

Відмова: Я майже новачок у БД: p

При цьому такий підхід до супутникової інформації негайно впливає на продуктивність:

  • Добре менше трафіку на основній таблиці
  • Гарні менші рядки на первинному столі
  • Погана потреба у супутникових даних означає, що необхідний ще один пошук
  • Погано більше місця займає, якщо всі об’єкти існують в обох таблицях

залежно від ваших вимог, ви можете це вітати, чи ні, але це, безумовно, питання, що слід враховувати.


-1

Я не бачу, як вашу схему можна назвати "незмінною".

Що відбувається, коли значення, збережене у додатковій таблиці, змінюється? Схоже, вам потрібно буде оновити цю таблицю.

Щоб база даних була справді непорушною, її потрібно підтримувати виключно "ВСТАВКИ". Для цього вам потрібен певний метод ідентифікації "поточного" рядка. Це майже завжди виявляється жахливо неефективним. Вам потрібно або скопіювати всі попередні незмінені значення над, або зібрати поточний стан з кількох записів, коли ви запитуєте. Виділення поточного рядка зазвичай потребує жахливого безладного SQL типу ( where updTime = (SELECT max(updTime) from myTab where id = ?).

Ця проблема виникає дуже багато в DataWarehousing, де потрібно зберігати історію даних протягом часу, і бути в змозі вибрати стан для будь-якого моменту часу. Рішенням зазвичай є "розмірні" таблиці. Однак поки вони вирішують проблему DW "хто був представником продажів минулого січня". Вони не забезпечують жодних переваг, які мають незмінні класи Javas.

На більш філософській ноті; Бази даних існують для зберігання «стану» (баланс банку, споживання електроенергії, точки догляду на StackOverflow тощо), намагаючись створити базу даних «без стану», здається досить безглуздою справою.


Для одного запису, WHERE id = {} ORDER BY updTime DESC LIMIT 1як правило, не надто неефективно.
Ізката

@Izkata - спробуйте покласти в hte посеред трьох таблиць приєднання :-)
Джеймс Андерсон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.