- PVSM.RU - https://www.pvsm.ru -

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Опечатки

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

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

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

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

Эвристика

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

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

Заключение

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

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

Автор: PatientZero

Источник [9]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/bazy-danny-h/391962

Ссылки в тексте:

[1] номер кузова: https://en.wikipedia.org/wiki/Vehicle_identification_number

[2] естественного ключа: https://en.wikipedia.org/wiki/Natural_key

[3] 50 лучших ресторанов мира: https://www.theworlds50best.com/

[4] Nobelhart & Schmutzig: https://www.nobelhartundschmutzig.com/

[5] синтетический ключ: https://en.wikipedia.org/wiki/Surrogate_key

[6] номер CPR: https://en.wikipedia.org/wiki/Personal_identification_number_(Denmark)

[7] Social Security Number: https://en.wikipedia.org/wiki/Social_Security_number

[8] биекции: https://en.wikipedia.org/wiki/Bijection

[9] Источник: https://habr.com/ru/articles/819619/?utm_source=habrahabr&utm_medium=rss&utm_campaign=819619