Правильно ли всегда иметь первичный ключ с автоинкрементами?

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

Это считается плохой идеей? Есть ли недостатки в этом? Иногда у меня будет несколько индексов, таких как id, profile_id, subscriptions , где id - уникальный идентификатор, profile_id ссылки на внешний id таблицы Profile и т. д.

Или существуют сценарии, в которых вы не хотите добавлять такое поле?

169 голосов | спросил Aruka J 15 PM000000110000002731 2016, 23:35:27

17 ответов


129

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

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

ответил GrandmasterB 15 PM000000110000005831 2016, 23:47:58
87

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

Если у вас есть таблица, в которой нет очевидных ключей, поле с автоматическим приращением кажется хорошей идеей. В конце концов, вы не хотите, чтобы выберите * из блога, где body = '[10000 символов]' . Вам лучше выбрать * из блога, где id = 42 . Я бы сказал, что в большинстве этих случаев вам действительно нужен уникальный идентификатор; а не последовательный уникальный идентификатор. Вероятно, вы захотите использовать универсальный уникальный идентификатор.

В большинстве баз данных есть функции для генерации случайных уникальных идентификаторов ( uuid в mysql, postgres. newid в mssql). Они позволяют создавать данные в нескольких базах данных на разных компьютерах в любое время без сетевого соединения между ними и по-прежнему объединять данные с нулевыми конфликтами. Это позволяет вам более легко настраивать несколько серверов и даже центры обработки данных, например, с помощью микросервисов.

Это также позволяет злоумышленникам угадывать URL-адреса страниц, к которым у них не должно быть доступа. Если есть https://example.com/user/1263 , возможно, есть https://example.com/user/1262 . Это может позволить автоматизировать эксплойт безопасности на странице профиля пользователя.

Существует также множество случаев, когда колонка uuid бесполезна или даже вредна. Допустим, у вас есть социальная сеть. Существует таблица users и таблица friends . Таблица друзей содержит два столбца userid и поле автоматического увеличения. Вы хотите, чтобы 3 дружил с 5 , поэтому вы вставляете 3,5 в базу данных. База данных добавляет идентификатор auto-increment и сохраняет 1,3,5 . Как-то пользователь 3 снова нажимает кнопку «добавить друга». Вы снова вставляете 3,5 в базу данных, база данных добавляет идентификатор автоинкремента и вставляет 2,3,5 . Но теперь 3 и 5 дружат друг с другом дважды! Это пустая трата пространства, и если вы думаете об этом, то и столбец автоинкремента. Все, что вам нужно, чтобы определить, являются ли a и b друзьями, для выбора строки с этими двумя значениями. Они вместе представляют собой уникальный идентификатор строки. (Возможно, вы захотите написать некоторую логику, чтобы убедиться, что 3,5 и 5,3 дедуплицируются.)

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

TL; DR: Используйте UUID вместо автоматического увеличения, если у вас еще нет уникального способа идентификации каждой строки.

ответил Filip Haglund 16 AM00000090000000031 2016, 09:08:00
57

Усовершенствованные ключи имеют в основном преимущества.

Но некоторые возможные недостатки могут быть:

  • Если у вас есть бизнес-ключ, вам необходимо добавить уникальный индекс в этот столбец, чтобы обеспечить соблюдение бизнес-правил.
  • При передаче данных между двумя базами данных, особенно когда данные находятся в более чем одной таблице (то есть мастер /деталь), это не прямолинейно, так как последовательности не синхронизируются между базами данных, и вам нужно будет создать таблицу эквивалентности сначала используя бизнес-ключ в качестве соответствия, чтобы узнать, какой идентификатор из исходной базы данных соответствует идентификатору в целевой базе данных. Это не должно быть проблемой при передаче данных из /в изолированные таблицы.
  • На многих предприятиях есть специальные, графические, точечные и перетаскиваемые инструменты для создания отчетов. Поскольку идентификаторы автоинкрементности не имеют смысла, пользователям такого типа будет трудно понять данные вне «приложения».
  • Если вы случайно измените бизнес-ключ, скорее всего, вы никогда не восстановите эту строку, потому что у вас больше нет людей, чтобы идентифицировать ее. Это вызвало ошибку на платформе BitCoin после .
  • Некоторые дизайнеры добавляют идентификатор к таблице соединений между двумя таблицами, когда ПК просто состоит из двух иностранных идентификаторов. Очевидно, что если таблица объединений находится между тремя или более таблицами, тогда идентификатор автоинкрементности имеет смысл, но тогда вам нужно добавить уникальный ключ, когда он применяется к комбинации FK для обеспечения соблюдения бизнес-правил.

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

ответил Tulains Córdova 16 AM00000010000003631 2016, 01:20:36
19

Просто, чтобы быть противоположным, нет, вам НЕ нужно всегда иметь числовое число AutoInc PK.

Если вы тщательно анализируете свои данные, вы часто определяете естественные ключи в данных. Это часто бывает, когда данные имеют неотъемлемый смысл для бизнеса. Иногда ПК являются артефактами из древних систем, которые бизнес-пользователи используют в качестве второго языка для описания атрибутов своей системы. Я видел номера транспортных средств VIN, используемые в качестве первичного ключа таблицы «Транспортное средство» в системе управления автопарком, например.

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

Иногда вы можете использовать AutoInc PK для создания значимого значения клиента, например. Номера политик. Установка начального значения на что-то разумное и применение бизнес-правил о ведущих нулях и т. Д. Это, вероятно, «лучший из обоих миров».

Если у вас небольшое количество значений, которые являются относительно статичными, используйте значения, которые имеют смысл для пользователя системы. Зачем использовать 1,2,3, когда вы можете использовать L, C, H, где L, H и C представляют жизнь, автомобиль и дом в контексте «Тип политики», или, возвращаясь к примеру VIN, как насчет использования «TO «для Toyota? Все автомобили Toyata имеют VIN, который запускает «TO». Для пользователей это менее важно, менее вероятно, что они могут ввести ошибки программирования и пользователя и даже могут быть пригодным для использования суррогатом для полного описания управленческих отчетов, упрощающих отчеты писать и, возможно, быстрее создавать.

Дальнейшее развитие этого, вероятно, является «мостом слишком далеко», и я вообще не рекомендую его, но я включаю его для полноты, и вы можете найти для этого хорошее применение. То есть, используйте Описание как основной ключ. Для быстро меняющихся данных это мерзость. Для статических данных очень , о которых сообщается в Все время , возможно, нет. Просто упомянуть об этом, чтобы он сидел там как возможность.

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

ИЗМЕНИТЬ Еще один важный момент, когда вам не нужен Autogenerated PK, - это случай таблиц, которые представляют собой пересечение двух других таблиц. Чтобы придерживаться аналогий автомобилей, у A есть 0..n аксессуаров, каждый аксессуар можно найти на многих автомобилях. Чтобы представить это, вы создаете таблицу Car_Accessory, содержащую PK из Car and Accessory и другую соответствующую информацию о датах ссылки и т. Д.

То, что вам не нужно (обычно), - это AutoInc PK на этой таблице - доступ к нему будет возможен только через автомобиль «скажите мне, какие аксессуары на этом автомобиле» или из «Аксессуар» расскажут, какие автомобили имеют этот аксессуар «

ответил mcottle 16 AM000000110000000731 2016, 11:57:07
12

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

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

ответил Brad Thomas 16 PM00000090000000531 2016, 21:22:05
9

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

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

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

Теперь мое главное:

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

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

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

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

ответил miroxlav 17 AM000000100000001731 2016, 10:28:17
8

Это не очень хорошая практика для лишних проектов. То есть - Неправильная практика всегда иметь автоинкремент int primary key, когда он не нужен.

Давайте посмотрим пример, где он не нужен.

У вас есть таблица для статей - это имеет первичный ключ int id , а столбец varchar с именем title .

У вас также есть таблица с полными категориями статей - id int primary key, varchar name .

Одна строка в таблице «Статьи» имеет id из 5 и title "Как приготовить гусь с маслом ". Вы хотите связать эту статью со следующими строками в таблице «Категории»: «Fowl» ( id : 20), «Goose» ( id : 12), «Cooking» ( id : 2), «Butter» (id: 9).

Теперь у вас есть 2 таблицы: статьи и категории. Как вы создаете связь между двумя?

У вас может быть таблица с тремя столбцами: id (первичный ключ), article_id (внешний ключ), category_id (внешний ключ). Но теперь у вас есть что-то вроде:

 | id | a_id | c_id |
| 1 | 5 | 20 |
| 2 | 5 | 12 |
| 3 | 5 | 2 | 

Лучшим решением является наличие первичного ключа, состоящего из 2 столбцов.

 | a_id | c_id |
| 5 | 20 |
| 5 | 12 |
| 5 | 2 | 

Это можно сделать, выполнив:

  Создать таблицу articles_categories (
  article_id bigint,
  category_id bigint,
  первичный ключ (article_id, category_id)
) engine = InnoDB;
 

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

UUID по своему определению уникальны, что делает то же самое, что и использование уникальных целых чисел. У них также есть свои дополнительные преимущества (и минусы) над целыми числами. Например, с помощью UUID вы знаете, что уникальная строка, которую вы ссылаетесь на точки на конкретную запись данных; это полезно в тех случаях, когда у вас нет 1 центральной базы данных или где приложения могут создавать записи данных в автономном режиме (затем загружать их в базу данных позднее).

В конце концов, вам не нужно думать о первичных ключах как о вещи. Вы должны думать о них как о функции, которую они выполняют. Зачем вам нужны первичные ключи? Чтобы иметь возможность однозначно идентифицировать определенные наборы данных из таблицы, используя поле, которое в будущем не будет изменено. Вам нужен конкретный столбец с именем id , или вы можете использовать эту уникальную идентификацию для других (неизменяемых) данных?

ответил anw 16 PM000000110000005331 2016, 23:09:53
7

Обычно я использую столбец «identity» (auto-incremennting integer) при определении новых таблиц для «долгоживущих» данных (записи, которые я ожидаю вставить один раз, и продолжайте бесконечно, даже если они закончатся «логически удалены», установив поле бит).

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

  • Если инкрементные идентификаторы будут слишком большой информацией для потенциального злоумышленника. Использование столбца идентификатора для служб данных с открытым доступом делает вас уязвимыми для «проблемы немецких танков»; если существует идентификатор записи 10234, то разумно, что записи 10233, 10232 и т. д. существуют, по крайней мере, для записи 10001, а затем легко проверить записи 1001, 101 и 1, чтобы выяснить, где был начат ваш столбец идентификации. V4 GUID, состоящие в основном из случайных данных, нарушают это поэтапное поведение по дизайну, поэтому только потому, что существует один GUID, GUID, созданный путем увеличения или уменьшения байта идентификатора GUID, необязательно существует, что затрудняет использование злоумышленником услуги, для однозадачного поиска в качестве инструмента сброса. Существуют и другие меры безопасности, которые могут лучше ограничивать доступ, но это помогает.
  • В таблицах перекрестных ссылок M: M. Это один из видов, но я видел это раньше. Если у вас есть отношение «много ко многим» между двумя таблицами в вашей базе данных, предлагаемое решение представляет собой таблицу перекрестных ссылок, содержащую столбцы внешнего ключа, ссылающиеся на PK каждой таблицы. PK этой таблицы должен быть всегда всегда составным ключом двух внешних ключей, чтобы получить встроенное поведение индекса и обеспечить уникальность ссылок.
  • Когда вы планируете много вставлять и удалять навалом в этой таблице. Вероятно, самым большим недостатком для столбцов идентификации является лишний hoopla, который вам нужно пройти, когда вы вставляете строки из другой таблицы или запроса, где вы хотите сохранить ключевые значения исходной таблицы. Вы должны включить «вставить идентификатор» (однако это сделано в вашей СУБД), а затем вручную убедитесь, что введенные вами ключи уникальны, а затем, когда вы закончите с импортом, вы должны установить счетчик идентификаторов в метаданных таблицы до максимального значения. Если эта операция происходит в этой таблице, рассмотрите другую схему PK.
  • Для распределенных таблиц. Столбцы идентификаторов отлично подходят для баз данных с одним экземпляром, пар отказов и других сценариев, когда один экземпляр базы данных является единственным полномочным органом всей схемы данных в любой момент времени. Тем не менее, есть только настолько большой, что вы можете пойти и все еще иметь один компьютер достаточно быстро. Доставка репликации или транзакций может предоставить вам дополнительные копии только для чтения, но также существует предел масштаба этого решения. Рано или поздно вам понадобятся два или более экземпляра сервера, обрабатывающие вставки данных, а затем синхронизирующие друг с другом. Когда возникнет такая ситуация, вам понадобится поле GUID вместо инкрементного, поскольку большинство СУБД предварительно настроены на использование части идентификаторов GUID, которые они генерируют в качестве идентификатора для конкретного экземпляра, а затем генерируют остальную часть идентификатора либо случайным образом или постепенно. В любом случае шансы столкновения между двумя генераторами GUID равны нулю, а столбец целочисленного идентификатора - это кошмар для управления в этой ситуации (вы можете пойти четным /нечетным, компенсируя семена и устанавливая приращение на 2, но если один сервер видит больше активности, чем другие, которые вы тратите впустую ID).
  • Когда вам нужно обеспечить уникальность для нескольких таблиц в БД. В системах учета, например, для управления Главной книгой (например, для каждой кредитной или дебетовой карты каждой учетной записи, которая когда-либо происходила, , поэтому он очень быстро растет) в виде последовательности таблиц, каждая из которых представляет один календарный месяц /год. Затем могут быть созданы представления, чтобы объединить их для отчетности. Логично, что это все очень большая таблица, но рубить ее облегчает работу по обслуживанию базы данных. Тем не менее, в нем представлена ​​проблема управления вставками в несколько таблиц (что позволяет начинать транзакции регистрации в следующем месяце, все еще закрывая последнее), не заканчивая дублирующимися ключами. Опять же, идентификаторы GUID вместо столбцов целочисленных идентификаторов являются подходящим решением, поскольку СУБД предназначена для генерации их по-настоящему уникальным способом, так что одно значение GUID будет отображаться один раз и только один раз во всей СУБД.

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

ответил KeithS 16 PM00000060000005531 2016, 18:19:55
7

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

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

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

Еще один вопрос - это тип данных ключа с автоматическим добавлением. Использование Int32 дает большой, но относительно ограниченный диапазон значений. Лично я часто использую столбцы bigint для Id, чтобы практически никогда не беспокоиться о том, что они заканчиваются.

ответил MatthewToday 16 AM00000030000002331 2016, 03:50:23
6

Как и другие люди, для инкрементного первичного ключа я сделаю один для GUID:

  • Гарантируется уникальность
  • У вас может быть меньше времени на поездку в базу данных для данных в вашем приложении. (Для таблицы типов, например, вы можете сохранить GUID в приложении и использовать это для извлечения записи. Если вы используете идентификатор, вам нужно запросить базу данных по имени, и я видел много приложений, которые делают это, чтобы получить PK и позже запрашивает его снова, чтобы получить полную информацию).
  • Это полезно для скрытия данных. www.domain.com/Article/2 Позволяет мне знать, что у вас есть только две статьи, тогда как www.domain.com/article/b08a91c5-67fc-449f-8a50-ffdf2403444a ничего мне не говорит.
  • Вы можете легко объединять записи из разных баз данных.
  • MSFT использует GUID для идентификации.

Изменить: Дублировать точку

ответил Three Value Logic 16 PM00000020000005231 2016, 14:12:52
6
  

Или существуют сценарии, в которых вы не хотите добавлять такое поле?

Конечно.

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

Более важно подумать о том, что на самом деле ID - это первичный ключ для ваших данных. Если у вас есть таблица с другим первичным ключом, вам не нужен идентификатор, и он не должен иметь его. Например, таблица (EMPLOYEE_ID, TEAM_ID) (где каждый сотрудник может находиться в нескольких командах одновременно) имеет четко определенный первичный ключ, состоящий из этих двух идентификаторов. Добавление столбца автоинкремента ID , который также является первичным ключом для этой таблицы, не имеет никакого смысла. Теперь вы кладете 2 первичных ключа вокруг, и первое слово в «первичном ключе» должно дать вам намек на то, что вы действительно должны иметь только один.

ответил AnoE 16 PM000000120000001231 2016, 12:52:12
3

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

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

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

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

ответил Zenilogix 18 AM00000050000003531 2016, 05:35:35
1

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

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

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

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

Поскольку единственной причиной введения суррогатного ключа является производительность, давайте предположим, что мы хотим, чтобы он был исполнен. Если проблема с производительностью - это объединение, мы обязательно хотим сделать наш суррогатный ключ настолько узким, насколько это возможно (не мешая аппаратной части, поэтому короткие целые числа и байты обычно отсутствуют). Производительность присоединения зависит от минимальной высоты индекса, поэтому 4-байтовое целое является естественным решением. Если ваша проблема с производительностью - это скорость ввода, то 4-байтовое целое также может быть естественным решением (в зависимости от внутренних компонентов РСУБД). Если вашей проблемой производительности для таблицы является репликация или несколько источников данных, чем какая-либо другая технология суррогатного ключа , будь то GUID или ключ из двух частей (идентификатор хоста или целое число), может быть более подходящим. Я лично не являюсь фаворитом GUID, но они удобны.

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

Специальные случаи

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

  2. Если ваша таблица никогда не будет больше, чем около ста строк, то высота индекса не имеет значения; каждый доступ будет выполняться сканированием таблицы. Однако сравнение строк по длинным строкам будет по-прежнему намного дороже сравнения 4-байтового целого и более дорогостоящего, чем сравнение GUID.

  3. Таблица значений code , введенных с помощью поля char (4) code , должна быть такой же, как и с 4 -байтное целое число. Хотя у меня нет доказательств этого, я часто использую это предположение и никогда не имел причины его пропустить.

ответил Pieter Geerkens 22 AM00000010000003731 2016, 01:34:37
0

Не только это не хорошая практика, на самом деле это описано как анти-шаблон в книге Билла Карвина по SQL Antipatterns.

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

ответил Pedro Werneck 16 PM00000060000002331 2016, 18:40:23
-2

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

Я обычно делаю указатели более очевидными именами полей, например ref_ {table} или аналогичной идеей.

Если не требуется внешнее указание на запись, вам не нужен идентификатор.

ответил Johnny V 15 PM000000110000000731 2016, 23:51:07
-2

Я бы не сказал, что это должно быть всегда . У меня есть таблица без уникального ключа - и она не нужна. Это журнал аудита. Никогда не будет обновления, запросы возвратят все изменения в том, что регистрируется, но это лучшее, что можно разумно сделать, и человек должен определить неправильное изменение. (Если бы код мог бы это запретить в первую очередь!)

ответил Loren Pechtel 17 AM00000020000003831 2016, 02:20:38
-3

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

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

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

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

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

ответил Archimedes Trajano 19 AM00000050000002331 2016, 05:13:23

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132