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

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

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

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

Уникальность

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

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

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

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

CREATE TABLE Restaurants (
    year TEXT NOT NULL,
    rank TEXT NOT NULL,
    restaurantName TEXT NOT NULL,
    cityName TEXT NOT NULL
);

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

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

В этом конкретном примере такое допущение, вероятно, будет соблюдаться. Пока. В конце концов, датасет не очень велик, а ресторанам такого уровня важно иметь узнаваемые названия. Я бы предположил, что в мире есть только один Nobelhart & Schmutzig.

Тем не менее, хороший архитектор ПО должен подвергать сомнениям подобные фундаментальные допущения. Действительно ли название и город — это естественный ключ? Легко представить, что это не так. Что, если мы дополним ключ ещё и страной? Отлично, но что, если у нас будет ресторан China Wok в Спрингфилде, США? [Прим. пер.: в США более сорока населённых пунктов с таким названием, поэтому его носит и вымышленный город из «Симпсонов».] Не совсем уникально. Говорите, добавить ещё и штат? Вероятно, всё равно ключ окажется неуникальным.

Идентификация

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

Но что насчёт «естественных» естественных ключей, так сказать? Например, номера кузова автомобиля. Это уже непрозрачное число, которое, вероятно, берётся из какой-то базы данных. А может быть, использовать персональный идентификационный номер? У нас в Дании есть номер CPR, и я знаю, что Social Security Number США примерно ему аналогичен.

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

Да, номер может уникальным образом идентифицировать человека, но обратное может и не быть истинным. У человека может быть несколько идентификационных номеров. По крайней мере, они могут добавляться со временем.

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

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

Это уникально не только для людей, но и для автомобилей, для велосипедов (тоже имеющих номер рамы), для сетевых карт и так далее.

Опечатки

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

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

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

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

Эвристика

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

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

Заключение

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

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

Комментарии (114)


  1. vis_inet
    05.06.2024 08:48
    +4

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

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

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


    1. PatientZero Автор
      05.06.2024 08:48
      +7

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


    1. Naf2000
      05.06.2024 08:48
      +2

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


    1. rdp
      05.06.2024 08:48
      +5

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


      1. vis_inet
        05.06.2024 08:48

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


        1. MiyuHogosha
          05.06.2024 08:48

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


    1. gd77
      05.06.2024 08:48
      +3

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


      1. vis_inet
        05.06.2024 08:48

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

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

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


        1. kinall
          05.06.2024 08:48

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


        1. SoundBlasteR
          05.06.2024 08:48

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


    1. Batalmv
      05.06.2024 08:48

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


    1. mentin
      05.06.2024 08:48

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


      1. vis_inet
        05.06.2024 08:48

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

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

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

        затем

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

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


  1. Audrius_P
    05.06.2024 08:48

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


    1. m_chrom
      05.06.2024 08:48
      +9

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


  1. petropavel
    05.06.2024 08:48
    +11

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


  1. Akina
    05.06.2024 08:48
    +3

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

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

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

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

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


    1. Ivan22
      05.06.2024 08:48
      +2

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


      1. Akina
        05.06.2024 08:48
        +12

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

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

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


        1. martin_wanderer
          05.06.2024 08:48
          +2

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


          1. Akina
            05.06.2024 08:48
            +1

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


            1. martin_wanderer
              05.06.2024 08:48
              +1

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


          1. Ivan22
            05.06.2024 08:48

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


        1. FAZAA
          05.06.2024 08:48

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


      1. GeniyZ
        05.06.2024 08:48
        +4

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


  1. Ivan22
    05.06.2024 08:48
    +17

    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 тут по мне еще и не на первом месте. И это я только одну таблицу увидел в этой БД


    1. MeGaZip
      05.06.2024 08:48
      +1

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


      1. Ivan22
        05.06.2024 08:48
        +1

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

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


        1. Dolios
          05.06.2024 08:48
          +4

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


    1. Gummilion
      05.06.2024 08:48
      +2

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


      1. ris58h
        05.06.2024 08:48
        +1

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

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


    1. Finesse
      05.06.2024 08:48

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


  1. nickolaym
    05.06.2024 08:48
    +2

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


  1. safari2012
    05.06.2024 08:48

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

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


    1. DustCn
      05.06.2024 08:48
      +11

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


      1. MiyuHogosha
        05.06.2024 08:48
        +6

        Мастер-ключ


        1. QASD
          05.06.2024 08:48
          +1

          кэп-ключ


      1. safari2012
        05.06.2024 08:48
        +1

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


    1. LF69ssop
      05.06.2024 08:48

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

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


      1. safari2012
        05.06.2024 08:48

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


    1. VasiliyLiGHT
      05.06.2024 08:48

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

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


  1. Kerman
    05.06.2024 08:48
    +1

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


    1. edo1h
      05.06.2024 08:48
      +2

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


      1. Kerman
        05.06.2024 08:48
        +1

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


        1. Ivan22
          05.06.2024 08:48
          +2

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

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


          1. MiyuHogosha
            05.06.2024 08:48

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


        1. edo1h
          05.06.2024 08:48

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


  1. Grikhan
    05.06.2024 08:48
    +4

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


    1. mmandaliev
      05.06.2024 08:48

      Амин!


    1. Ivan22
      05.06.2024 08:48
      +1

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


      1. Grikhan
        05.06.2024 08:48

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


        1. Ivan22
          05.06.2024 08:48

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

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

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

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


  1. Portnov
    05.06.2024 08:48
    +8

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


    1. MiyuHogosha
      05.06.2024 08:48

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


      1. navferty
        05.06.2024 08:48

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


    1. vikarti
      05.06.2024 08:48

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


  1. kidaig
    05.06.2024 08:48
    +12

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


    1. sigprof
      05.06.2024 08:48
      +2

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


      1. vis_inet
        05.06.2024 08:48
        +1

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


        1. Yumado
          05.06.2024 08:48
          +1

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

          Хе.

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

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

          Сережа*

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

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


          1. Naf2000
            05.06.2024 08:48

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


            1. Yumado
              05.06.2024 08:48

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

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

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

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


              1. Naf2000
                05.06.2024 08:48

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

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


  1. hogstaberg
    05.06.2024 08:48
    +2

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


    1. Ivan22
      05.06.2024 08:48
      +5

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

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


    1. vvbob
      05.06.2024 08:48

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

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


      1. karavan_750
        05.06.2024 08:48
        +1

        Дополню ваш коммент примером неуникального VIN.


      1. hogstaberg
        05.06.2024 08:48

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


    1. PAL_habr
      05.06.2024 08:48
      +1

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

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


      1. surly
        05.06.2024 08:48

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


      1. DBalashov
        05.06.2024 08:48
        +1

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

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


        1. surly
          05.06.2024 08:48

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


  1. Kahelman
    05.06.2024 08:48

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

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

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

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

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

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

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

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

    Year, rank, name, city

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

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

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

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

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

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

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

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

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


  1. Kahelman
    05.06.2024 08:48
    +1

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

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

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

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

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

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

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

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

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


    1. Ivan22
      05.06.2024 08:48
      +5

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


      1. Kahelman
        05.06.2024 08:48

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


        1. tsukasa_mixer
          05.06.2024 08:48
          +4

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

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

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


        1. Karington
          05.06.2024 08:48
          +2

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


        1. Ivan22
          05.06.2024 08:48

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


    1. MiyuHogosha
      05.06.2024 08:48

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

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


      1. Kahelman
        05.06.2024 08:48

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

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


        1. Kahelman
          05.06.2024 08:48

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

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


        1. navferty
          05.06.2024 08:48
          +3

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

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

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


          1. Ivan22
            05.06.2024 08:48

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


            1. navferty
              05.06.2024 08:48

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


    1. plumqqz
      05.06.2024 08:48

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


      1. Ivan22
        05.06.2024 08:48
        +1

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


  1. sYB-Tyumen
    05.06.2024 08:48
    +1

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

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


  1. Karington
    05.06.2024 08:48
    +10

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

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

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

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

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

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


    1. Akina
      05.06.2024 08:48
      +2

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

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

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


      1. morijndael
        05.06.2024 08:48

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

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


        1. markedo
          05.06.2024 08:48

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


    1. plumqqz
      05.06.2024 08:48

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

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

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

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


      1. Naf2000
        05.06.2024 08:48

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


        1. plumqqz
          05.06.2024 08:48

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


          1. Naf2000
            05.06.2024 08:48

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


            1. plumqqz
              05.06.2024 08:48

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


              1. Naf2000
                05.06.2024 08:48

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

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


                1. plumqqz
                  05.06.2024 08:48

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


  1. OlegUV
    05.06.2024 08:48
    +2

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

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

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


  1. Batalmv
    05.06.2024 08:48
    +3

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

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

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

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

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

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

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

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

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

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

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

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

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

    Резюмируя:

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

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


    1. Yumado
      05.06.2024 08:48

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

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


  1. kinall
    05.06.2024 08:48

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


  1. vladnet1
    05.06.2024 08:48

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

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


    1. jmdorian
      05.06.2024 08:48
      +1

      Ну как вам сказать...


      1. Naf2000
        05.06.2024 08:48
        +2

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


        1. Ivan22
          05.06.2024 08:48

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


      1. artptr86
        05.06.2024 08:48

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


  1. nApoBo3
    05.06.2024 08:48

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


  1. speshuric
    05.06.2024 08:48
    +1

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

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


    1. Akina
      05.06.2024 08:48
      +1

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

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

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


      1. speshuric
        05.06.2024 08:48

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


  1. Kahelman
    05.06.2024 08:48

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

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

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

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

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

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

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

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

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


    1. Ivan22
      05.06.2024 08:48

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

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