Чи повинна система з кількома орендарями з SQL Server 2016, Shard або мати ізоляцію орендарів через окрему базу даних на орендаря?


12

Враховуючи випадок використання:

  • Дані орендаря не повинні перетинати розмови, одному орендарю не потрібні дані іншого орендаря.
  • Кожен орендар потенційно може мати великий обсяг історичних даних.
  • SQL Server розміщується в екземплярі AWS EC2.
  • Кожен орендар географічно віддалений.
  • Існує намір використовувати сторонні інструменти візуалізації, такі як PowerBI Embedded
  • Очікується, що обсяг даних з часом зростатиме
  • Вартість системи обмежена.
  • Рішення повинно бути доцільним без цілодобового виробничого дозволу
  • Розчин повинен мати можливість масштабування горизонтально.
  • Загальна кількість орендарів менше 50

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

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

Відповіді:


16

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

Коли ви створюєте додаток для багатьох клієнтів, існує два поширених способу проектування бази даних:

  • Варіант A: Помістіть усіх клієнтів в одну базу даних
  • Варіант 2: Створіть одну базу даних на кожного клієнта

Розміщення всіх клієнтів в одній базі даних

Це просто: просто додайте таблицю Клієнта у верхній частині схеми, додайте таблицю ClientUsers, щоб переконатися, що люди бачать лише власні дані, і ми вирушаємо.

Переваги такого підходу:

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

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

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

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

Поміщення кожного клієнта у його власну базу даних або осколок

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

Переваги такого підходу:

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

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

Легша масштабованість на декількох серверах. Коли нашому додатку потрібно більше енергії, ніж ми можемо отримати від одного сервера, ми можемо розділити бази даних між декількома серверами. Ми також можемо розподілити навантаження географічно, ставлячи сервери в Азії чи Європі, щоб бути ближче до клієнтів.

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

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

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

Який із вас підходить?

Немає правильного вибору: ви повинні знати сильні та слабкі сторони своєї компанії. Візьмемо для прикладу двох моїх клієнтів.

Компанія A відмінна в налаштуванні апаратної продуктивності. Вони справді дуже хороші в тому, щоб вивести останні апаратні показники з обладнання, і вони не проти замінити апаратне забезпечення SQL Server на 12-18-місячному циклі. (Вони оновлюють веб-сервери кожні 4-6 місяців!) Їх ахіллесова п’ята - це надзвичайні вимоги дотримання та безпеки. Вони мають неймовірні потреби в аудиті, і їм просто простіше реалізовувати пуленепробивні елементи управління на одному сервері, єдиній базі даних, ніж керувати цими вимогами у тисячах баз даних на десятках серверів. Вони обрали одну базу даних, один сервер, багато клієнтів.

Компанія 2 відмінна в практиці розвитку. Управління змінами схем та розгортанням коду у тисячах баз даних для них просто не є проблемою. У них є клієнти по всьому світу, і вони цілодобово обробляють транзакції кредитними картками для цих клієнтів. Їм потрібна можливість географічного поширення навантаження, і вони не хочуть замінювати сервери по всьому світу кожні 12-18 місяців. Вони обрали по одній базі даних для кожного клієнта, і це окупається, коли вони починають розміщувати сервери SQL в Азії та Європі для своїх офшорних клієнтів.


"У вашому випадку в PowerBI наявність всіх в одній базі даних значно полегшить управління з'єднаннями". Зараз PowerBI Embedded не забезпечує захист рівня рядків, і, отже, кожен орендар в одній базі даних викликає певні сумніви щодо цього випадку використання, дивіться: community.powerbi.com/t5/Developer/… , з огляду на цю інформацію, чи можете ви перефразувати це чи запропонувати альтернативу чи виправити своє розуміння?
ДС

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

Я просто скажу, що розгортання в більш ніж одній базі даних не так вже й погано, як ви здасте це здоровим. У 2017 році у нас є багато варіантів, які дозволяють дуже легко розгортати зміни до 1, 5 або 900 баз даних. І якщо у вас є винятки для конкретних клієнтів, вони зазвичай можуть бути введені до цих баз даних таким чином, щоб вони не заважали загальному коду.
Аарон Бертран

5

Ще одного розгляду я ще не бачив в інших відповідях.

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

Зворотний неправда. Консолідація багатьох баз даних для одного орендаря потребуватиме значно більше роботи.


4

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

* Це не завжди порушує нормалізацію, але може. Наприклад, якщо у вас є Personі в PersonAddressтаблиці. PersonТаблиця буде мати в TenantID, PersonIDякості первинного ключа. У PersonAddressтаблиці буде TenantID, PersonID, AddressTypeIDосновний ключ із тим, що я пропоную.

Зазвичай просто PersonIDвистачить, тому що ви можете приєднатись до Personстолу, щоб знайти його Tenant. Я пропоную вам перенестися TenantIDдо кожної наступної таблиці, навіть коли більш тонкий ключ буде працювати.

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


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

3
Але навіть якщо ви вирішили перенести TenantID у дочірні таблиці, чого вам не потрібно робити, більш широкий ключ не означає, що нормалізація "порушена". Так само, як вибір GUID для ідентичності (більш широкий ключ) не порушує нормалізацію, а також вибір більш широкого природного ключа замість використання сурогатів взагалі.
Аарон Бертран
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.