Повернутися до всіх запитань

Що таке поліморфні (Polymorphic) звʼязки?

Junior/Middle/SeniorDatabases
Зустрічали на інтервʼю:1 користувач

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

Розберемо приклад

Уявимо, що ми створюємо соціальну мережу і в нас є такі сутності, як posts, photos, videos. Нам потрібно реалізувати можливість додавати коментарі до цих сутностей. Найбільш очевидні способи реалізувати таку задачу це:

  1. Зробити окрему таблицю під кожен тип контенту, наприклад, post_comments, photo_comments, video_comments і так далі.
  2. Також можна зробити універсальну таблицю comments і звʼязати її з іншими через foreign key. Наприклад, postId, photoId, videoId.

Ці способи робочі, але при додаванні нових типів контенту нам доведеться або створювати нові таблиці в базі даних, або створювати нові foreign keys, що ускладнить бізнес-логіку API і структуру даних в БД.

Популярним рішенням в подібних ситуаціях є поліморфний звʼязок. Суть його в тому, що ми будемо мати одну універсальну таблицю comments з колонками entity_id і entity_type.

  1. entity_id - ідентифікатор запису, до якого ми додали коментар. Важливо розуміти, що це не foreign key, а просто число чи рядок (якщо використовуємо UUID чи подібний вид ID).
  2. entity_type - тип контенту, до якого ми лишили коментар. Наприклад, post чи photo. Ця колонка потрібна нам для того, щоб розуміти, по якій таблиці робити пошук. Наприклад, ми хочемо вибрати всі коментарі до post з ID=1, і таким чином ми відфільтруємо тільки ті коментарі, що мають entity_type=post.
posts
+----+-------------+
| id | title |
+----+-------------+
| 1 | My trip |
+----+-------------+

photos
+----+------------------+
| id | url |
+----+------------------+
| 5 | photo.jpg |
+----+------------------+

comments
+----+----------------+----------------+------------------+
| id | text | entity_id | entity_type |
+----+----------------+----------------+------------------+
| 1 | Nice post! | 1 | post |
| 2 | Beautiful pic | 5 | photo |
+----+----------------+----------------+------------------+

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

  1. Referential integrity - так як в нас відсутні зовнішні ключі, база даних не може гарантувати цілісність даних і звʼязків між ними. Частково цю проблему можна вирішити додаванням CHECK і Partial Indexes, але це більше костиль, ніж реальне рішення.
  2. JOIN - запити в базу даних стають складнішими і повільнішими через відсутність зовнішніх ключів. Ця проблема стосується систем з великою кількістю даних і інтенсивним навантаженням, тому в таких випадках краще використовувати способи, про які я згадував спочатку.
  3. CASCADE - так як вони неможливі без зовнішніх ключів, нам потрібно реалізовувати їх на рівні бізнес-логіки, що має прямий вплив на роботу транзакцій, так як порушує консистентність даних (Consistency, якщо говорити про ACID).

Зустрічав на інтервʼю?

Коментарі (0)

Увійдіть, щоб залишити коментар

Поки що немає коментарів. Будьте першим!