Рекомендации по ID для баз данных

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

Теперь я создаю базу данных пользователей... и, основываясь на этом совете, "userid mediumint auto_increment" был бы неприемлем. Особенно, если я планирую использовать этот идентификатор в качестве основного идентификатора для пользователя. (например, если я разрешаю пользователям изменять свое имя пользователя, то отследить имя пользователя будет труднее, чем числовой идентификатор пользователя... требующий каскадных внешних ключей и многого другого.) Электронные письма меняются, имена пользователей могут меняться, пароли меняются.. ., но идентификатор пользователя должен оставаться постоянным навсегда.

Понятно, что auto_increment предназначен только для surrogate_keys. То есть это полезный ярлык только тогда, когда у вас уже есть первичный механизм идентификации, но его не следует использовать в качестве «врожденного идентификатора» для данных. Создание случайного UUID выглядит интересно, но случайность меня отталкивает.

И поэтому я спрашиваю: каковы наилучшие методы создания идентификационного номера «первичного ключа»?


person Dragontamer5788    schedule 03.12.2010    source источник
comment
Как насчет совета вашего профессора вы пришли к выводу, что автоинкрементные целые числа не подходят в качестве уникальных идентификаторов для пользовательских данных?   -  person jwheron    schedule 04.12.2010
comment
Целые числа с автоматическим приращением предсказуемы и не содержат средств обнаружения ошибок. По крайней мере, я ожидаю, что практика идентификации профессионального уровня будет несколько непредсказуемой и самоидентифицирующей. Например, номера кредитных карт имеют одну цифру контрольной суммы, а это означает, что если человек неправильно введет кредитную карту, вероятность того, что она будет принята, составляет всего 1/10. Они также достаточно непредсказуемы, поэтому хакер не может просто ввести случайные номера кредитных карт в Amazon и надеяться, что у него есть действующий номер кредитной карты. Точно так же хакер не должен запускать атаки по словарю с предсказуемыми UID.   -  person Dragontamer5788    schedule 04.12.2010
comment
Я не понимаю твоего сравнения здесь. Я был бы ошеломлен, если бы компании, выпускающие кредитные карты, использовали фактические номера кредитных карт в качестве идентификаторов базы данных, а не хранили их как некий надежно защищенный атрибут в таблице. Ваш комментарий подразумевает, что знание идентификатора будет своего рода бэкдором в базу данных. Аутентификация в некотором роде должна быть защитой от несанкционированного доступа к данным, а не от знания случайных значений базы данных.   -  person jwheron    schedule 04.12.2010
comment
@ Dragontamer5788 - Я утверждаю, что в наши дни эта контрольная цифра в CC не так полезна, как запрос к компании CC с номером, именем и значением CCV для проверки ее владельца. Единственный способ узнать наверняка, действителен ли CC, — это запросить авторитетный источник.   -  person Thomas    schedule 04.12.2010
comment
@Thomas: я не имею в виду, что номера CC проверяются только их контрольной цифрой. Тем не менее, это кажется преимуществом с небольшими затратами. Контрольные цифры могут быть легко реализованы в эффективном Javascript, и пользователь может сразу понять, что он допустил ошибку при наборе текста. IE: контрольные цифры нужны для удобства использования, а не для безопасности.   -  person Dragontamer5788    schedule 04.12.2010
comment
@ Dragontamer5788 - Я не согласен с тем, что мало затрат, особенно связанных с изменениями. Требуются усилия, чтобы вывести алгоритм контрольной цифры и поддерживать его перед лицом изменения идентификатора. Кредитные карты широко распространены в том смысле, что многие компании могут генерировать ценности (аналогично примеру судоходной компании, который я привел в своем посте). Если строящаяся система всегда будет единственным авторитетным источником, то контрольная цифра почти не дает преимуществ ИМО.   -  person Thomas    schedule 04.12.2010


Ответы (6)


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

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

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

person Bill    schedule 03.12.2010
comment
Этот ответ имеет для меня наибольшее значение. Спасибо. - person Dragontamer5788; 04.12.2010

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

person Samuel Neff    schedule 03.12.2010
comment
станет ли это значение в конечном итоге слишком большим для хранения многих пользователей? - person Mike; 18.03.2015
comment
@mike, используйте 64-битный int в коде, и у вас никогда не закончатся значения при отслеживании пользователей. 9 223 372 036 854 775 807 возможных значений или вдвое больше, если вы используете целое число без знака 64. - person Samuel Neff; 19.03.2015
comment
Вы частично правы. Но мы должны иметь в виду, что если мы не предоставляем идентификатор пользователю, то есть для поиска, мы вообще не воспользуемся преимуществами кластерных индексов. - person kerzek; 12.08.2015
comment
@kerzek, можете ли вы объяснить это утверждение о неиспользовании кластерных индексов? чаще всего идентификаторы используются в объединениях, поэтому кластеризованный индекс уменьшит дополнительный шаг при сборе данных, полученных в результате объединения. Кроме того, вы также предполагаете конкретную реализацию с кластеризованными индексами. Не все механизмы хранения MySQL поддерживают кластеризованные индексы. - person Samuel Neff; 12.08.2015
comment
Разве это не проблема, когда вы используете это извне, что люди могут легко получить информацию, которую они не должны получать (например, как быстро растет ваша пользовательская база)? - person Martin Thoma; 16.08.2018
comment
Что вы думаете о рекомендациях по Формирование идентификатора Witty&Alan? - person Martin Thoma; 16.08.2018
comment
@MartinThoma Я думаю, что это не имеет никакого отношения к этому вопросу. Витти и Алан говорят об идентификаторе пользователя в сценарии, где идентификатор используется для внешней идентификации пользователей. Когда мы говорим об идентификаторе пользователя в базе данных, мы говорим о внутреннем идентификаторе. - person Samuel Neff; 16.08.2018
comment
@SamuelNeff Хорошо. Итак, читая эту статью, я могу понять, почему хотелось бы иметь внешний идентификатор, который имеет несколько разных свойств. А зачем иметь внутренний идентификатор, отличный от внешнего? Не думаю, что разница в размерах будет иметь значение. - person Martin Thoma; 17.08.2018
comment
@MartinThoma Мне не интересно спорить. Если вы не видите преимуществ, ничего страшного, вы можете использовать то, что предпочитаете. Также имейте в виду, что статье 15 лет, а этому ответу 8 лет. Лучшие практики и рекомендации меняются. - person Samuel Neff; 17.08.2018

Сравнение SSN с автоматически увеличивающимися целыми числами — это яблоки и апельсины. Лично я избегаю GUID/UUID/UID, если только в таблице не будет так много записей, что использование целого числа станет неэффективным или неразумным.

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

person Community    schedule 03.12.2010

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

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

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

Даже если вы реализовали UUID и сгенерировали какое-то произвольное случайное число, это все равно просто число. Аутентификация Active Directory использует идентификаторы GUID для своих идентификаторов, но также требует, чтобы пользователи предоставляли имена пользователей и пароли. Использование большего или меньшего типа данных в качестве столбца идентификатора не означает, что я могу умыть руки от какого-либо другого типа аутентификации или безопасности.

person jwheron    schedule 03.12.2010
comment
Я как раз собирался расширить свой пост по этому поводу. Число, любое число само по себе никогда не является достаточным для определения достоверности и подлинности человека, с которым оно связано. - person Thomas; 04.12.2010

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

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

person Andrew White    schedule 03.12.2010

В конце концов, способ проверить, действителен ли данный идентификатор пользователя, — это сама система. То есть ваша система является официальным источником этих идентификаторов. Является ли 555-45-9999 действительным SSN? Единственный способ узнать наверняка — попросить Службу социального обеспечения найти его и сопоставить с именем человека, утверждающего, что у него есть этот номер. Конечно, мы можем использовать схему идентификатора SSN, чтобы предварительно предположить, действительна ли она. Однако только поиск в их системе скажет нам наверняка. Потребность в контрольных цифрах может возникнуть в сильно распределенных системах, где, например, вы можете позволить другим людям генерировать номера, учитываемые вашей системой (например, транспортные компании, которые позволяют клиентам генерировать свои собственные номера для отслеживания). Поскольку именно ваша система будет автоматически генерировать идентификаторы, лучшее, что может сделать для вас контрольная цифра, — это помочь в элементарном способе проверки при вводе данных или поиске.

person Thomas    schedule 03.12.2010