Спільний доступ до однієї послідовності первинного ключа в базі даних?


14

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

Я молодший розробник програмного забезпечення, а не DBA, тому я все ще вивчаю багато основ хорошого дизайну баз даних.

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

Edit2: Щоб відповісти на запитання в коментарях, це для Oracle 11g, але мені було цікаво на рівні, що не має бази даних. Якщо це питання залежить від бази даних, мені було б цікаво дізнатися чому, але в такому випадку я б шукав відповіді, специфічної для Oracle.


2
Зазвичай це страшна ідея з міркувань продуктивності.
Philᵀᴹ

1
Насправді є більша користь у наявності кожної таблиці зі своїм незалежним діапазоном первинних ключів. Але тільки в тому випадку, коли ви дивитеся купу ідентифікаторів, які ви могли б сказати, це один обліковий запис, той - PurchaseHeader і т.д. (Так, я працював із такою системою багато років тому.)
RLF

Які СУБД ви використовуєте? Oracle? Postgres? DB2?
a_horse_with_no_name

1
Чи можливо ви неправильно трактували, що він мав на увазі? Може, він не був таким буквальним?
JamesRyan

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

Відповіді:


13

Прийнятний? Звичайно. Поширені? Ні Вигідний? Сумнівні.

На моїй старій роботі ми успадкували систему, де у них був центральний генератор послідовностей (це була система SQL Server задовго до того, як SEQUENCEбула введена в SQL Server 2012). Це насправді не було вузьким місцем продуктивності і не повинно бути, якщо ви не генеруєте сотні тисяч значень в секунду. Але це зробило весь код набагато складнішим, ніж це мало бути, без поважних причин. Намір дизайну полягав у тому, щоб, якщо чомусь у системі присвоєно ідентифікаційне значення 12, то лише одне в системі могло мати ідентифікатор 12. Це мені здавалося досить тупим, і я цього ніколи не розумів. Якщо у мене є клієнт із CustomerID = 12, чому це не дозволяє мені мати замовлення з OrderID = 12?

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


Якби вам довелося вибирати щось подібне і просто використовувати унікальні ідентифікатори в якості первинних ключів, ви б мали перевагу (хоча відповідь, ймовірно, "це залежить")? Схоже, що GUID вирішить проблему так само, за винятком того, що ви отримаєте стандартну реалізацію, а не прокатати власний централізований генератор первинних ключів. Очевидно, що використання послідовності в SQL 2012 дозволило б виконати обидві речі, але якщо припустити, що хтось перебуває на старій версії?
SqlRyan

2
@SqlRyan Мені потрібно зрозуміти, чому OrderID повинен повністю відрізнятися від CustomerID. Я майже напевно не використовував би GUID для цього; налаштування діапазонів ідентичності може бути кращим (клієнти починаються з 1, замовлення починаються з 1000000 і т.д.), надіславши попередження про те, коли ви наблизилися до вичерпання діапазону курсу.
Аарон Бертран

1
@SqlRyan - використання погано реалізованого GUID як кластеризованого первинного ключа може спричинити всілякі проблеми. Як сказав Аарон, ідентичність набагато краще відповідає цілі.
Макс Вернон

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

@AaronBertrand Або ж використовуйте прості цілісні ідентифікатори та додайте код до початку, коли вони стоять перед клієнтом. напр. I1337, C1337 чітко рахунок-фактура або клієнт
JamesRyan

7

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

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

SQL-сервер може генерувати послідовні GUID за замовчуванням, викликаючи функцію newSequtialID (), тому немає таблиці виданих ключів для підтримки та не блокує вузьке місце.

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

Ціна, звичайно, є простором і його проблематичним, коли ви намагаєтеся перенести дані до сховища даних / куба, де швидкість / розмір визначається за допомогою менших клавіш Integer.

Я переконаний, що ми уникали багатьох помилок у нашому додатку внаслідок їх використання.


4

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

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

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


2
Ви можете додати детальну інформацію про те, як створюється вузьке місце і чому це погана ідея.
Макс Вернон

2

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

використання послідовного номера в якості основного ключа є таким же, як і кожна таблиця, має стовпець Identity, і лише цей стовпець використовується в PrimaryKey. мати єдиний порядковий номер у БД повинен мати певне використання, але з точки зору PrimaryKey я не розумію причини. Наприклад, в одному з проектів Datawarehouse, над яким я працював, у нас стовпчик називається LoadBatchID, і від ETL до звітування про 50% всієї таблиці є цей стовпець, але в деяких місцях він має інше значення. ми використовували унікальний процесор як генератор чисел, щоб переконатися, що ми не знаходимо конфліктів, а також допомагаємо нам відслідковувати вихідний файл, звідки надходили дані та що відбувається на різних етапах ETL.


2

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

create table god_entity (
  id bigserial primary key
);

create table some_table (
  id bigint primary key references god_entity(id),
  ...
);

create table some_other_table (
  id bigint primary key references god_entity(id),
  ...
);

create table comment (
  id bigint primary key references god_entity(id),
  ...
);

create table entity_comment (
  entity_id bigint not null references god_entity(id),
  comment_id bigint not null references god_entity(id),

  primary key (entity_id, comment_id)
);

Зазвичай це не робиться. .

Не знаю про характеристики продуктивності.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.