Как стать автором
Обновить

Вы пожалеете об использовании естественных ключей

Уровень сложностиПростой
Время на прочтение5 мин
Количество просмотров19K
Всего голосов 45: ↑42 и ↓3+55
Комментарии125

Комментарии 125

Не совсем понял, как механик определил, что у машины неправильный VIN-номер?

И что значит "неправильный"?

Его же нанесли непосредственно на заводе изготовителе.

В базу данных с ошибкой введён, наверно

Номер в документе отличается от выбитого на кузове

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

Отнюдь, у официальных автодилеров + сервисов есть доступ к определённым информационным системам производителей.

Это отдельная база. Скорее всего у производителя все в порядке. Но у производителя нет доступа к данным клиента

Как вариант VIN в документах и VIN в "мозгах" был разный - когда-то меняли ЭБУ. Механик просто прописал в ЭБУ номер из документов.

В принципе, да, это возможно.

Но для прописывания в мозгах приносят ноут к машине, а не идут к компьютеру.

Возможно, описание ситуации неполное или недостаточно подробное.

Строго говоря, ноут уже мог быть подключён с самого начала работ. И "подошёл к компьютеру" - это два шага от капота (где выбит VIN) до салона (где на сиденье стоит ноут)

Все пациенты врут. Dr.House

Контрольный разряд? Либо очевидное несовпадение модели

Это официальный механик, который вносит данные в государственную базу. Соответственно у него есть (1) документы владельца с регистрацией машины, (2) государственная база данных, в которую надо внести сведения о проверке, (3) собственно машина. Что-то разошлось, либо документы либо база разошлись с машиной. Цифре на машине наверное верят, а остальному нет.

Я это всё понимаю.

Меня смутило, что сначала

механик, выполнявший осмотр, сообщил мне о том, что у машины неправильный номер кузова

затем

Но механик просто подошёл к своему компьютеру, чтобы исправить ошибку.

Т.е. неправильность номера он оценил у машины, без обращения к компьютеру.

Механик знал что очепатки в регистрационных номерах делаются специально при помощи специально обученных людей для специальных целей !

Думаете, для тестирования баз данных на устойчивость к изменению естественных ключей?

Не хватает истории "я угнал машину, перебил номера, привёз на сервис, смотрите, говорю, тут номер кузова неправильный, исправьте там у себя"

Если кого-то (или что-то) заставить делать два дела сразу, как правило оба делаются хреновато.

Так и тут. Назначение первичного ключа (ПК) - уникальная идентификация записи. Всё. И проистекающее из этого использование - поддержание средствами СУБД целостности, в том числе ссылочной. По-хорошему, значение ПК, исходя из его функции и связанных с этим применений, не должно быть видно пользователю и нигде, и никогда - за абсолютной для этого юзера ненадобностью.

Однако на ПК навешивают ещё одну функцию - обеспечение требования уникальности. Точнее, эта функция у него уже есть, но её расширяют в область взаимодействия с пользователем. И вот именно с этого момента, приобретя фактически вторую функцию, ПК начинает работать "не очень". А паровозом к этому "не очень" идут все описанные в статье (и ещё куча не описанных) проблемы. Ну и кто тут ССЗБ? явно не сам ПК.

Бывают ли случаи, когда правильно использовать естественные ключи при проектировании базы данных?

Конечно. Композитный естественный первичный ключ в adjacency table.

композитный ключ - это само по себе антипаттерн

композитный ключ - это само по себе антипаттерн

Эмм... это почему же? какой смысл в связующую таблицу на два поля добавлять ещё и синтетический ключ - чтобы раздуть её полем, которое никогда и нигде не будет использовано? и чтобы в явной форме создать уникальный индекс, который тоже сожрёт дополнительное дисковое пространство без какого-либо профита?

Какие у вас есть основания называть композитный ключ антипаттерном - ну может кроме того, что он вам лично не нравится?

И всё-таки иногда такой смысл есть - когда приходится эту таблицу постепенно перекачивать в другую БД и оказывается важно знать, какая запись уже выгружена, а какая - ещё нет

Для идентификации записи - в том числе для указанного случая,- в т.ч. и существует первичный ключ. И нет никакой разницы, композитный он или нет.

При миграции данных важно, чтобы в разных таблицах был единый способ идентификации записи

ну исключения бывают, и это таблицы на которые никакие другие ссылаться никогда не будут. Но если вдруг выяснится что нужен FK на таблицу с композитным ключем, начинается веселье

Отмечу, что не композитный ключ быстрее (но не всегда) работает при апсертах и джойнах

Для таблиц организующих связь других, как многие ко многим, композитный ключ — самое то!

CREATE TABLE Restaurants (    

year TEXT NOT NULL,    

rank TEXT NOT NULL,    

restaurantName TEXT NOT NULL,    

cityName TEXT NOT NULL);

Однако, согласно курсу, будет естественным определить ключ для таблицы Restaurants как комбинацию restaurantNamecityName и year.

Ладно студенты, но как нормальный датамоделер может в таблицу ресторанов запихнуть year (это же год в котором выставлена оценка) ну и еще и сама оценка (Rank). Это все свойства не ресторана, а оценки. Т.е. нужна отдельная таблица Ranks где есть FK на ресторан, year и сам rank. А ресторан уникально определяется самим собой, иначе вообще что будет хранится в таблице Restaurants при наличии рейтингов за несколько лет?

p.s. так что проблема с естественным PK тут по мне еще и не на первом месте. И это я только одну таблицу увидел в этой БД

Может year это дата основания/открытия ресторана

может и так. Однако потом текст "Допущение здесь заключается в том. что название и город идентифицируют ресторан уникальным образом. "

Если название и город уже ключ - зачем год???

В моём городе 3 макдоналдса отрылись в один год. Хз, что они там собрались идентифицировать..

Никого не волнует, какая у ресторана была оценка 20 лет назад - смотрят по текущей. Даже если для каких-то целей нужна история оценок, если мы часто фильтруем рестораны по оценке, имеет смысл сделать денормализцию и таки добавить оценку к ресторану.

имеет смысл сделать денормализцию и таки добавить оценку к ресторану

Имело бы, если бы там не было года в таблице. Если это таблица ресторанов, то год не нужен. Если это таблица оценок, то не нужны название и город.

Оверинжениринг тоже приводит к проблемам. Смотреть нужно по задачам, которые база должна решать.

В этой таблице на самом деле нужно изменить все поля.

year TEXT должен быть числом или датой,

rank TEXT тоже по всей видимости должен быть числом,

restaurantName стоит назвать просто name, restaurantуже есть в названии таблицы,

cityName города стоит хранить в отдельной таблице.

Про биекцию непонятно. Это что-то плохое, или это что-то недостижимое, или что автор хотел сказать? Фраза построена... странно.

Неправильный номер кузова и мне вбивали ещё 90е годы на отечественные жигули. Исправили, правда тогда это всё тянуло за собой гемор и очереди. Сейчас наверное проще решать.

А ещё мне на правах категорий ABC в те же "лихие 90е" случайно категорию A напечатали с прочерком. И поверх синей печатью два раза зафигачили "разрешено". Всё бы ничего, но через 10 лет при смене прав пытались отказать, хотя я принес карточку из автошколы с записью о сданном экзамене. Случайно мимо проходил знакомый, сосед по подъезду, а по совместительству капитан том самом подразделении ГАИ, где всё оформлялось. Он и помог решить.

Вот суть вопроса - нахрен биекции когда у тебя в соседях капитан подразделения!!

Мастер-ключ

кэп-ключ

А я понятия не имел. Сосед жил двумя этажами ниже и мы не очень то общались.

Странная история.

А при утере прав вам бы вовсе отказали в замене? Или таки подняли бы свою картотеку в которых все ваши категории указаны?

Откуда мне знать? Слава богу, следующая замена прошла штатно.

Сейчас наверное проще решать

Буквально вчера смотрел ролик на канале iling show, они пытались рафик на учёт поставить. Если вкратце: на кузове два VIN, один неполный, второй полный, но первые три цифры писали краской, которая за время испарилась. На всё про всё ушло 2,5 месяца. Сначала восстановили VIN (набили новый), потом добивались исправления опечатки в документах. Правильно - X1D, в доках X1B.

Прочитав текст, я сделал вывод, что под "естественным" ключом подразумевается ключ из чужой ИС. Собственно вывод предсказуем: не доверяй никому. Особенно так делать нельзя, если планируется держать данные из разных сторонних ИС.

Причём тут чужие ИС?
Набрал в гугле «естественный ключ», читаю:
Естественный Ключ (ЕК) – набор атрибутов описываемой записью сущности, уникально её идентифицирующий (например, номер паспорта для человека) или Суррогатный Ключ (СК) – автоматически сгенерированное поле, никак не связанное с информационным содержанием записи.
Даже не хочется перефразировать

При том, что номер паспорта - это ключ из чужой информационной системы, например. Он ни в одном месте не естественный )

так и есть, что в одной системе суррогатный ключ - то в другой естественный.

А когда данные проходят через пяток разных систем, они могут в итоге обрасти полудюжиной ключей разной степени суррогатности.

А когда их присоединят к мос.ру, они становятся композитным?

то, что существует сторонняя ИС, в которой хранится номер паспорта, это несущественное в данном случае знание. доступа к той ИС у нас всё равно нет.
другой пример, у нас есть архив записей с видеокамеры, в качестве естественного ключа для инцидентов можно использовать дату + время начала события (я не говорю, что это удачное решение, просто иллюстрация естественного ключа, который не связан с какой-то внешней ИС).
или для всяких файлообменных вещей в качестве естественного ключа для файла часто используется хэш от его содержимого.

...набор атрибутов описываемой записью сущности, уникально её идентифицирующий (например, номер паспорта для человека)

Просто оставлю это здесь.

Ну, во первых, натуральный ключ - это всегда сущность предметной области. Выбирать необязательный атрибут в качестве ключа - так себе занятие. Номер кузова - это не номер всего автомобиля, а номер его кузова (удивительно, кто бы мог подумать). Для ГАИ это будут одни обязательные атрибуты, для СТО - другие. Например, для СТО - это объект обслуживания - vin автомобиля. При этом надо определить в результате бизнес-анализа vin из документа или vin с автомобиля? Что должно соответствовать чему? Что из этого мастер-данные, а что - производная. Адрес ресторана - это не сущность предметной области ресторанного бизнеса - это предметная сущность почтовой службы. Больше того, в самой постановке "мы создали БД ресторанов и надо выбрать ключ" - критическая ошибка постановки. Чтобы выбрать состав БД нужно сначала понять - зачем? В чем ее бизнес-значение? Что вы хотите от БД с именем ресторана, годом, оценкой и городом? Ваша табличка БД в целом лишена всякого смысла в отрыве от контекста, не только ключ. Может быть вы табличку с объектами в год по городам считаете и вам все равно на имя и rank? Ну тогда ключи "город" и "год" - вполне себе ключи.

Амин!

В теории все верно. Но на практике в датамоделенге есть определенные шаблоны и устоявшийся порядок вещей. Например если есть таблице поле ID - на 90% мы знаем что это PK и есть, ну или если где-то в БД существует таблица с названием "Restaurants" то мы ожидаем что там будет список ресторанов и гранулярность: одна строка = один ресторан. Всякое исключение из этого правила должно быть обоснованно и дважды серьезно продумано.

Мне нравится этот шаблон и устоявшийся порядок на 90%! Предположение - мать всех ошибок. Чтобы не ошибаться в 10% случаев (на самом деле, в подавляющем большинстве случаев), не надо предполагать. Совершенно с вами согласен, что название должно отражать суть таблицы. Но имя- это имя. Это якорь после того, как вы узнали что это за таблица на самом деле - чтобы эффективно вспомнить. Может быть это ресторан года в данном городе? Или вообще представленность СЕТЕЙ ресторанов по городам с какого года? Предположений может быть очень много. Необходимо исходить из бизнеса, а не предположений изолированного в подвале DBA. Если в таблице есть ID - это скорее всего вообще синтетический ключ, а не натуральный. И если вы будете использовать именно его, то в большинстве случаев зря потратите ресурсы и время.

Может быть это ресторан года в данном городе? 

вот и не надо так делать, созда "Restaurants_year_rank" с FK на таблицу ресторанов, и все будут счастливы.

Необходимо исходить из бизнеса,

Это все равно что сказать - необходимо иметь полную документацию. Верное, но абсолютно бесполезное утверждение. Ибо в реальном мире всегда приходится заниматься дебагингом кода без документации, ну и демоделингом модели данных заодно. И тут грамотно (по шаблонам) созданная модель - это как красиво написанный код, помогают, в разы ускоряя процесс

Имхо главная проблема натуральных ключей — в том, что "натуральность" меняется со временем, и делать соответствующие доработки в ПО может оказаться слишком дорого. Ну, грубо говоря, ИНН сейчас есть у всех граждан РФ и не меняется в течение жизни, так что если вы делаете что-то типа госуслуг, то почему бы не сделать его первичным ключом? А через год принимают закон, по которому ИНН становится можно менять по заявлению, и... ой.

А потом там закодированы данные региона и налоговой в той ИНН. Аока. А в итоге это может стать артефактом, если отделение переедет?

Нет, при переезде ИНН остаётся - то есть там закодирован скорее "регион в момент получения ИНН". Но с самим посылом о том, что ИНН - плохой первичный ключ, я согласен. Например, наличие (пусть и вследствие ошибки) двух ИНН у одного человека вполне возможно.

Нет, при переезде ИНН остаётся

Забавно... на моём бланке о постановке на налоговый учёт перечислены причины для смены ИНН, и их довольно много - я, например, в начале нулевых менял "при смене пола" (мне при оформлении пол вбили "женский", а обнаружил я это лишь спустя полгода, при оформлении на новую работу) - тогда это было возможно, но как же были сконфужены сотрудники налоговой, когда к ним пришёл бородатый парень, и заявил, что хочет изменить ИНН из-за смены пола. Сейчас глянул в нормативку - да, уже причин для смены ИНН практически не осталось, но так было не всегда.

А вот СНИЛС изначально создавался неизменяемым, и "госуслуги" как раз его используют в качестве "ПК".

Ну так выше был пример - хватило дури закодировать пол в местный аналог ИНН а потом решили что если мы считаем что человеку пол менять (ну или приводить записи в официальных документах с ним) можно - то надо и тут править. УПС.

Свой первый естественный ключ в БД я использовал более 20 лет назад. Это было поле ИНН в таблице контрагентов. Ведь он же такой индивидуальный и такой уникальный! По крайней мере, так казалось вчерашнему студенту. Спустя пару недель начались небольшие неудобства. Потом начались проблемы, стопорение бизнес-процессов, путаница в контрагентах, кажется даже умудрились деньги отправить в неправильную организацию. Меня пинали все - от главбуха до уборщицы.
Автор совершенно прав: никогда, ни при каких обстоятельствах не используйте естественные ключи. Даже если вам угрожают пистолетом.

В общем случае ИНН организации не является уникальным идентификатором — например, ИНН филиала вуза может совпадать с ИНН головного вуза (в результате чего регулярно возникают различные проблемы).

Верно, в этом случае у них должны быть разные КПП.

а в случае ИП что должно быть разным для разных филиалов ?

Хе.

Не ИНН не КПП не являются PK

Бух-ия заведет одного контрагента с несколькими наименованиями

Сережа*

Сережа услуги*

Сережа долг по суду*

У ИП филиалов нет. Но насчет не может быть ключом - согласен

Согласно ст. 55 ГК РФ, обособленное подразделение может открывать только юридическое лицо. 

Мы говорим и употребляем в слово филиал. В данном контексте и в частном случае, например склад за городом.

Так что филиал возможен, есть и будет.

А то что вы называете словом филиал с отдельным КПП это обособленное подразделение.

Тогда нужно выработать словарь терминов. Потому что одно дело говорить об официальных юр.лицах и ИП. Это одно. Говорить о партнерах (обычно формальный набор юр.лиц в руках общих владельцев) - это другое, а можно говорить о точках доставки (склад за городом). И это третье.

Потому что доставку при продаже разумно организовать с точностью до точки. А вот взаиморасчеты вести - нет. Однако тут можно вести взаиморасчеты (параллельно) по юр.лицам и по партнерам (менее формально и в суд с этим не пойдешь).

Я так и не понял что мешает одновременно использовать в базе номер кузова как первичный ключ (ну он же реально должен быть уникальным, а если вы пытаетесь забить в базу такой же номер второй раз, то должно ругнуться и сказать: "такой номер уже есть, вот он, давайте разбирайтесь кто из них правильный, а кто с опечаткой/машину спёртую водит") и дать возможность пользователю его менять?

Ну сама по себе возможность менять (да еще и пользователю) PK - это очень плохо, ибо ссылочная целостность может поплыть в самых неожиданных местах.

Vin кузова - это просто свойство автомобиля, такое же как и модель и цвет и госновмер. PK же суррогатный существует независимо и вообще пользователям не должен быть виден

VIN хоть и редко, но все-таки разрешено на законных основаниях перебивать. Вот например недавно смотрел видосик с приключениями автоблоггеров, которые ставили на учет старую машину, у которой на заводе номер был пробит с ошибкой. Предыдущим владельцам его поставили на учет как есть, а им отказались ставить, из-за некорректности. Экспертиза, заключение, разрешение на смену номера, и вот у машины изменился VIN. Если в БД он будет использоваться в качестве PK, то вы тут-же поимеете лютый гемор с ссылочной целостностью, с интеграциями с другими системами, возможно даже появятся дубли машин, одни со старым вином, другие с новым..

В общем - если не хочется отстрелить себе в будущем ноги, лучше реально не использовать ВИН в качестве первичного ключа, и уж тем более не стоит давать пользователям возможность эти ПК редактировать хоть каким-то способом. Вообще им незачем его видеть даже.

Окей, уговорили. Мир неидеален, а VIN неуникален)

Уникальность это в данном случае не самое главное. Если вин будет первичным ключе, то его изменение может потребовать каскадных изменений во всех связях, где он используется. Вот это проблема.

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

Если СУБД поддерживает конструкцию «ON UPDATE CASCADE», то львиная доля проблем со ссылочной целостностью снимается.

А если не поддерживает?
В таких случаях (общие рассуждения), наверное, лучше задаваться вопросом не: "а если всё хорошо", а вопросом: "а если всё плохо".
Т.е. это вопрос не максимизации выгоды при хорошем стечении обстоятельств, а минимизации потерь при плохом стечении обстоятельств. А так-то у нас и программы все без ошибок пишут. :)

А если не поддерживает, тогда всё сложнее. В любом случае при проектировании базы данных нужно учитывать возможности и особенности СУБД, на которой эта база будет крутится.

Это без вопросов. В данном случае даже лучше, наверное, сказать не "нужно", а "приходится".
Думаю, что автор говорит как раз о трудностях, которые могут возникнуть и которые желательно сразу предусмотреть и избежать или минимизировать.
Но это, конечно, не значит, что они возникнут обязательно и везде.

> Если вин будет первичным ключе, то его изменение может потребовать каскадных изменений во всех связях, где он используется

И изменённые записи в БД сразу перестанут соответствовать уже десяткам и сотням выданным на их основе печатным документам и далее по цепочке другим документам на их основе :)

Эта проблема возникнет даже в том случае, когда ВИН не является ключом.

Почитав статью и комментарии возникло беспокойство по поводу качества специалистов по информационным системам.

Посмотрите нормальную книжку по реляционным базар данных: первичный ключ это набор атрибутов сущности, которые ее однозначно идентифицируют.

Отсюда следуют 1,2,3 и N-ая формы нормализации

Вот и статья на хабре ищется.

https://habr.com/ru/articles/254773/

Про искусственные ключи в реляционной теории пробе ничего не говориться, хотя тут смотря как атрибуты интерпретировать.

Далее надо смотреть на предметную область.

Если у нас есть таблица как в примере:

Year, rank, name, city

То в общем случае с точки зрения реляционной теории это нормальное представление данных.

В конце концов мы тут одним избежать хранения дублирующиеся данных в БД.

Допустим у нас 3 ресторана с одним именем: МакДональдс в городе Мухосранск, которые в 2024 году имели ранк 5

Му очень прекрасно ужимаем данные до 1 записи:

2024,5, Макдональдс, Мухосранск

Поскольку запись уникальна , то она представляет собой первичный ключ для таблицы.

И если в начале года откроется еще один ресторан Макдональдс, который в середине 2024 года получит ранк 5, то нам ничего не придётся менять.

Как мы будем различать рестораны Макдональдс 1, Макдональдс 2 и т.д. Это дело десятое и зависит от конкретной предметной области.

Но естественные или искусственные первичные ключи это не вопрос реляционной теории.

Кстати, тут в голову пример пришёл, который показывает что искуственнне ключи только создают видимость что решают проблему:

Если у вас в базе два Ивана Иванивича, которые родились в один день в одном городе.

Вы же используете искусственные ключи как профессионал:

У вас в базе id1 -Иван Иванович ,

id2-Иван Иванович, а поскольку вы ещё и продвинутый, то в качестве ID вы Guid использовали.

И вот к вашему кассиру приходит Иван Иванович за зарплатой…

Вы как его идентифицировать будете?

Он же ваш GUID не знает?

Так что при наличии искусственного ключа проблема не решается без дополнительных аттрибутов.

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

Вы добавляете атрибуты в запись, которые делают набор уникальным, т.е по сути- естественные ключи ( номер паспорта)

Внезапно, номер паспорта в маштабах страны не является уникальным.
Да и он может многократно менятся в течении жизни.

т.е. синтетический ключ, это защита от проблем расширения и маштабирования системы в течении жизненного цикла.

Т.е. как пример, я потерял как я думал свидетельство о рождении.
Сходили заказали востановить, мне выдали новое и мы нашли старое.
И вот в чем соль у меня теперь 2 свидетельства с разными номерами, но оба легитимны.

При смене номера паспорта как быть?

наличие естественных (бизнес) ключей, не отменяет необходимость иметь суррогатный

В принципе да. это скорее неверное использование ключа. Понадобится SELECT employee WHERE ITN = "табельный номер".

GUID останется когда человек уйдет с работы и ему не надо платить зарплату, а вот данные о нем надо хранить

Если есть табельный номер то guid не нужен. Поскольку табельный номер это уникальный ключ в пределах предприятия.

Вы предлагаете генерить два ключа и говорите что это класс.

Товарищи минусующие, вы бы хоть пару строчек черкнули….

Перейдите по. Ссылке на оригинал и почитайте комменты. Там как-раз пишут что синтетические ключи это не панацея.

  • Табельный номер могут ошибочно присвоить дважды одному человеку.

  • По решению начальства табельные номера "обнуляются", и начинают выдаваться заново с номера 1 (пропуская те номера, которые присвоены ещё работающим сотрудникам)

  • Табельные номера могут совпадать у разных сотрудников в результате слияния двух организаций.

да и вообще собрали БД работников холдинга из 50 предприятий. И-и-и-и-и??

Это были примеры случаев, когда использование табельного номера (используемого, например, в бухгалтерских документах) в качестве первичного ключа в БД может привести к проблемам. Ваш случай тоже вполне укладывается в этот ряд.

Вы правы, искусственный ключ по сути утверждение - "а вот это мы будем называть гнвоерк" и не более.
Соответственно, в некоторой базе с искусственным ключом один Иван Иваныч запросто может явиться во множестве ипостасей, как индийские боги, и искусственные ключи просто позволяют скрыть эту проблему, причем в первую очередь от разработчика.
По-хорошему, как мне кажется, надо иметь а)искусственный ключ, причем желательно не int, а что-то типа UUID или подобного б)уникальный естественный ключ (или что-то более замысловатое)

так и есть, причем в аналитике даже термин уже давно для б) cуществует- "бизнес ключ"

Да. Естественный ключ часто может являться злом.

Но когда мы студентами обнаружили, что существует Erwin Examiner, оказалось, что самая распространенная ошибка - это забыть отслеживать уникальность естественного ключа при наличии синтетического.

Поделюсь своим, никому не нужным опытом

Тезис первый -- естественный ключ это очень хорошо, но только в том случае, если он никогда не меняется.

Тезис второй: Естественный ключ всегда будет меняться.

Исходя из тезисов 1 и 2: Лучше всегда использовать синтетический ключ.

Адрес дома, VIN автомобиля, фамилия, имя, отчество, рост, номер паспорта, номер СНИЛС, ИНН, корпоративный email, логин, код сотрудника, да даже пол и цвет кожи -- это всё не константные значения. И не изменятся они только в том случае, если вы не доживёте до их изменения: уволитесь или умрёте раньше.

Если кто-то не верит в тезис номер 2: то подумайте о том, что границы стран двигаются и даже у дома может измениться название улицы и страна в которой он находится

Если кто-то не верит в тезис номер 2

Достаточно учесть, что любой естественный ключ присваивается (его значение создаётся) человеком. Прямо или косвенно (через какую-то систему нумерации и учёта) - неважно. Даже штамп времени - и тот меняется при изменении параметров часового пояса или, не приведи господи, системы летосчисления. И вообще - человек, он, знаете ли, такой проказник...

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

Даже штамп времени - и тот меняется при изменении параметров часового пояса или, не приведи господи, системы летосчисления.

<зануда>Unix timestamp как раз не прыгает, потому что это просто количество секунд с определенного момента. Все переводы часов накладываются на него уже при конвертации в человеческий формат</зануда>

<зануда>Уже давно существую теории, что время - величина не равномерная и может течь по-разному. Равность секунд это лишь презумция -- договорённость между людьми для удобства. И эта презумция вполне может измениться. Не говоря уже о том, что даже самые точные часы имеют погрешность и через миллионы лет может набежать сдвиг в дни и годы между фактическим событием и временным штампом.</зануда>

"Тезис второй: Естественный ключ всегда будет меняться."
Разумеется нет. Вот, предположим, пришел некий Пупкин Василий Насильевич ставить машину с вином таким-то на учет, о чем и занесли факт в таблицу "заявления о постановке на учет" - дата-время, фио, паспортные данные, вин, что-то еще.

Все, теперь делай что хочешь, но прошлое у греков не могли изменить даже боги, чего уж тут говорить о разработчиках.

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

Паспортные данные, время и вин в данном случае - отличный неизменный естественный ключ (я от него брал бы хеш, так удобнее и короче, но в общем разница непринципиальная).

А завтра стукнуло ему 45 лет и пришлось идти менять паспорт

И что? Он с новым паспортом окажется в прошлом?

Задача идентификации в этих "прошлых" данных становится сложнее

Я так понимаю, вы столь юны, что вам паспорт еще не меняли, иначе бы вы увидели там раздел "сведения о ранее выданных паспортах" :-)
Завидую. Честно :-)
А вот у меня там все вплоть до советского.
Но это вторичный вопрос; на самом деле если там хранить изменяемые данные, то невозможно точно ответить на простой вопрос - "кто именно подавал заявления на такую-то дату?"

Спасибо за комплимент, недавно менял в 45 лет паспорт. Я же не сказал невозможно, но становиться "сложнее".

Получается в итоге номер/серия паспорта это ключ только паспорта (капитан очевидность), а вот по паспорту можно получить данные человека. Но мы уже уходим в область философии.

Так это философия и есть в чистом виде, см. Аристотель, "Категории". Вот прям с первых строк.

Подход в принципе неправильный, не с той стороны.

Автор взял сущность и набрал каких-то её атрибутов, а потом задаётся вопросом - как сделать из них уникальный ключ сущности. Это как тыкнуть пальцем в небо - может получится уникальный ключ, а может и нет.

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

Мне кажется, что статья чуток не о том

Лично я всегда по дефолту рекомендую (я уже сам не занимаюсь кодингом) использовать синтетический ключ как primary. Причина проста. Цена вопроса копеешная, а ссылочная целостность и адресация объекта/записи на высоком уровне.

Но есть проблема идентификации. Внутри системы все прекрасно, как и везде, пока не пришли пользователи и не начали тыкать в кнопки. А что делать, когда вы с чем-то интегрированы. Тут ваш синтетический ключ уверенно встал и вышел, так как очевидно ваша система не пуп Земли и не MDM для всего сущего. Общение идет по естественным ключам в большинстве случаев, так как общим знанием об объекте являются именно есть естественные параметры.

И поэтому задачу управлять естественными ключами, которые заданы бизнес моделью никто не отменяет. Если в вашу систему прилетел пакет с данными про "Васю", то вам надо искать именно Васю. Если у вас их много, то естестввенные ключи никак не помогают

Ну или в примере

Так как номер кузова — очевидный кандидат на должность естественного ключа, я заранее предвидел, что изменение этого номера будет или невозможно, или приведёт ко всевозможным каскадным эффектам

Ну ок, поменял. Допустим в системе есть запись о машине и свыязанная с ней запись о владельце. Они связаны foreign key который построен опираясь на синтетический ключ. Но прикол в том, что этот ключ живет внутри системы. Когда автора статьи остановит полиция, она теоретически сверит регистрационный номер, номер кузова и ФИО владельца.

И "правильная" структура никак не защищает от

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

Конечно, для софта естественный ключ решает потенциальную проблему дубликатов VINa, если бы он использовался как primary key. Но если окажется, что есть реальный дубликат, т.е. два авто с одинаковым VIN кодом, то хорошо все буде в базе и только.

В реальном мире проблема останется

В конечном итоге, вне зависимости от вашей уверенности в том. что естественный ключ стабилен и корректно отслеживает сущность, случаются ошибки данных.

Вот тут как по мне ошибка. Синтетический ключ отслеживает ЗАПИСЬ о сущности, которую элементарно можно подменить другой записью. А вот естественный ключ отслеживает именно СУЩНОСТЬ, так как сколько бы записей о "Васе" не было бы в разных системах, он все равно сначала Вася, а потом уже 0c0d49a0-d2e5-4f04-86a4-31c421ed4090

Резюмируя:

  • для консистентности данных очевидно надо использовать синтетические ключи

  • для идентификации - естественные

коммент тянет на статью по уникальности записей и поиску в БД. речь шла про РК.

100% лучше синтетический ключ. Есть возможность для оптимизации "запись - чтение"

Не по конкретной статье, а вообще по переводам. Во-первых, как, интересно, даже не заметив плашки "перевод" я уже на третьем абзаце понял, что это именно он? Во-вторых, что за манера оставлять ссылки на англоязычную википедию? Например, статья про биекцию есть и на русском.

Тоже проблема нашли, вообще пользоваться естественными ключами можно только когда они регламентированы каким то органом серьёзным, например для валюты есть международный код.

В других случаях проще пользоваться guid. А то у вас получится что если пользователь ошибся в названии города, то все это уже другой ресторан. Дичь

Пример двух разных валют, да

это еще один пример того что даже таблицу валют надо с суррогатным PK делать. А то ведь наверняка кто-то на название валюты заложится

Так это формально разные валюты: белорусский рубль до деноминации 2016 года (BYR) и после (BYN). Аналогично, российский рубль до деноминации RUR (810), после — RUB (643).

Всегда используйте суррогатные первичные ключи за исключением случаев когда вы абсолютно уверены, что это решении не проходит функциональные или не функциональные требования. Все.

Как-то бессмысленно дискутировать с переводом, но таки напишу. Синтетические ключи - неплохой (часто лучший) выбор для сущностей, т.е. строк, в БД обладающих идентичностью. 2 человека - как ни меняй их имена, пол, дату рождения и паспорт всё равно остаются двумя разными людьми. Используйте синтетический ключ.
Если же запись таблицы не является сущностью или её сущность полностью описывается естественным ключом, то синтетический ключ только поломает всё.
Примеры, когда сущность полностью описывается ключом: таблица недействительных паспортов, таблица праздничных дней (часто любой календарь).
Примеры, когда запись таблицы не является сущностью: отношения многие ко многим (там просто составной ключ родительских таблиц какие бы они ни были).

Плюс есть гора особых случаев. Не всё сводится к классическим справочникам и OLTP. Есть и time-series и OLAP, и куча того, что вообще отвратительно в таблицы ложится.

Примеры, когда запись таблицы не является сущностью: отношения многие ко многим

Неоднозначный (не скажу плохой) пример.

Контрпример. Таблица прав X. Таблица объектовY. Связующая таблица XY, хранящая право на объект. Таблица пользователей Z. И связующая таблица XYZ, которая хранит права пользователей на объекты, т.е. связь между XY и Z. В этом случае право на объект, которое хранит связующая таблица XY, есть ни что иное как самая настоящая сущность, которая к тому же может иметь собственные дополнительные атрибуты, например, срок актуальности.

Так я как раз про то, что нет таких максималистских по-детски правил, что "всегда синтетика" или "естественный ключ есть? а если найду?". Более того, догматичность тоже не догма: иногда отход от догм позволяет увидеть крутое решение, иногда приводит к винегрету решений.

Рекомендация использовать синтетический ключ это вопрос реализации. Логично что проще работать с числом, короткой строкой чем с набором из 100 аттрибутов.

Но это не гарантирует вас от проблем.

Давайте посмотрим на натариуса: вы пришли к нему регистрировать сделку по покупке квартиры.

Он в книгу записал: запись номер 10, квартира расположеная по адресу, ,,, приобретена гражданином Ивановым,….

Если вы через год паспорт/фамилию поменяете или улицу город переименуют - сделка от этого не станет ничтожной.

И натариус не будет вам записи подчищать каждый раз когда вы паспорт/фамилию меняете.

Если с паспортом /фамилией ещё боле менее просто что-то подтвердить, то с изменением названий улиц/городов все гораздо сложнее.

Тем не менее человечество давно эту проблему решило. Полагаясь исключительно на естественные ключи.

И только у программистов почему-то проблемы возникают

ну гораздо проще отслеживать историю изменения любых атрибутов сущности имея неизменный сурогатный PK , чем не имея его.

p.s. А так-то человечество и берестяными грамотами обходилось конечно

Можно поинтересоваться, каким именно образом человечество эту проблему решило полагаясь на естественные ключи? Не говоря уже о том, что номер паспорта, это точно суррогатный ключ, а адрес и фио, очень спорно, они по большому счету, тоже суррогатные, поскольку существуют для идентификации объекта и не являются его свойствами.

не, ну так-то и ДНК последовательность суррогат

Вот уже дет 100-200 в западных Европа существует право собственности, которое регистрируется и перерегистрируется. При этом никаких проблем отсутствие синтетических ключей не создаёт.

проблема идентификации сущности не решается присвоением ей искусственного ключа.

Есть у вас база данных компаний.

Вы, как тут предлагалось, провариваете каждой компании GUID чтобы проце было оствлеживать изменения.

Допустим у вас есть компании : Id/name

1/a

2/b

3/c

4/d

5/e

Теперь у вас компания а делятся на 2:

a1 и a2,

Компания b покупает компанию а1,

Из Компании b выделяется компания b2

Компания “с” покупает компании b2, d,e

Ну и кому вы какой из существующих guid(Id) присвоите чтобы отразить что???

Вот уже дет 100-200 в западных Европа существует право собственности, которое регистрируется и перерегистрируется. При этом никаких проблем отсутствие синтетических ключей не создаёт.

Боюсь производительность любой ИТ системы работающий так же как право собственности в западных Европах вам сильно не понравится. И проблем там масса, которые решаются в судебном порядке. При этом суррогатные ключи там используются в полный рост, начиная от адреса, заканчивая различными номерами удостоверений личности, свидетельств и справок. При этом данная система не является жестко связной, т.е. вы не можете в любой момент времени без анализа человеком построить все существующие в подобной системе зависимости, т.е. анализ этих данных фактически возможен только руками оператором.

проблема идентификации сущности не решается присвоением ей искусственного ключа.

В общем смысле нет. В ИТ системах да. Есть ключ, он однозначно идентифицирует объект с точки зрения информационной системы.

Ну и кому вы какой из существующих guid(Id) присвоите чтобы отразить что???

Это зависит от того, что вы подразумеваете под абстракцией "компания" в данной конкретной системе. Эта абстракция будет определять границы идентифицируемого объекта и правила поведения в случаях когда эта изоляция нарушается. Например у вас есть банан, ид такой-то, вы съели банан, это все еще тот же самый объект или уже нет, что произошло с исходным объектом, он преобразовался, разделился, уничтожен, вариантов очень много и они зависят от того, как описана предметная область в рамках ит системы.

Ну и кому вы какой из существующих guid(Id) присвоите чтобы отразить что???

Да никакой! Появившиеся новые компании - это новые экземпляры сущности с точки зрения ИС, и они получат новые, свежесгенерированные, значения идентификатора. Исчезнувшие компании будут удалены либо (если вы говорите, что надо отслеживать изменения) их записи будут помечены сроком окончания валидности. И где-то в отдельной таблице будет описываться тип окончания валидности с необходимыми дополнительными атрибутами.

PS. Меня обычно за эту фразу полоскают, но моё мнение - уникальный синтетический ключ должен идентифицировать запись в течение срока жизни таблицы. Да-да, не отдельной записи, а именно всей таблицы. И удаление записи - не помеха.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории