В одному з проектів, побудованих на Rails версії 7.0.8, виникла потреба в розділенні даних в базі даних Postgres за клаузою tenant id. Це означає, що потрібно створити одну таблицю, яка буде автоматично розділяти дані на підтаблиці згідно ідентифікатора орендаря.
Ситуація полягає в наступному: існує таблиця
1 |
billing_schedule_lines_old |
, що визначає схему даних. Потрібно змінити цю таблицю так, щоб вона стала основною таблицею, від якої будуть утворюватися підтаблиці, розділені за значенням ідентифікатора орендаря (tenant_id).
Перш за все, ми створюємо нову таблицю з іменем
1 |
billing_schedule_lines |
, що буде мати ту ж саму структуру, що й
1 |
billing_schedule_lines_old |
, за допомогою конструкції
1 |
LIKE billing_schedule_lines_old INCLUDING DEFAULTS |
. Ця команда створить нову таблицю з усіма колонками та типами даних з вихідної таблиці, а також з усіма значеннями за замовчуванням.
Далі, ми вказуємо, що
1 |
billing_schedule_lines |
буде розділена за значенням поля
1 |
tenant_id |
за допомогою команди
1 |
PARTITION BY LIST (tenant_id) |
.
Наступним кроком є створення підтаблиць для кожного орендаря. Для цього ми використовуємо блок коду на мові PL/pgSQL, що дозволяє динамічно створювати нові таблиці згідно значень ідентифікаторів орендарів.
Після виконання цих кроків, дані в базі даних будуть розділені за клаузою tenant id. Однак, після внесення цих змін, можуть виникнути деякі проблеми з операціями з даними, такі як отримання останнього запису (
1 |
BillingScheduleLine.last |
) або масове вставлення даних. Розглянемо ці проблеми детальніше.
Помилка
1 |
ActiveRecord::IrreversibleOrderError: Relation has no current order and table has no primary key to be used as default order |
виникає тоді, коли ActiveRecord не може визначити порядок сортування для запиту. Це може відбутися, якщо в таблиці відсутній ключ сортування або ActiveRecord не може автоматично визначити його.
Помилка
1 |
PG::NotNullViolation: ERROR: null value in column "id" of relation "billing_schedule_lines_491" violates not-null constraint |
виникає, коли спроба масового вставлення даних (bulk insert) в підтаблицю завершується неуспішно через відсутність значення для поля “id”, яке є обов’язковим.
Такі ж самі проблеми можуть виникнути й при оновленні даних в розділених таблицях.
Для вирішення цих проблем можна використати наступні підходи:
Загалом, розділення даних в Postgres для Rails 7.0.8 є можливим завдяки використанню вбудованих засобів бази даних та динамічного створення підтаблиць. Проте, для успішної реалізації потрібно врахувати можливі проблеми з операціями з даними та використати відповідні стратегії вирішення цих проблем.