Как выбрать UUID, автоинкремент / ключи последовательности и таблицы последовательности для первичных ключей базы данных? - PullRequest
28 голосов
/ 10 января 2011

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

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

Какое значение имеют такие вопросы, как распределенное / множественное ведение, требования к производительности, использование ORM, безопасность и тестирование?

Есть неожиданные недостатки, с которыми можно столкнуться?

1 Ответ

29 голосов
/ 10 января 2011

UUID,

Если они не генерируются "в возрастающей монотонной последовательности", они могут сильно повредить / фрагментировать индексы. Поддержка генерации UUID зависит от системы. Несмотря на то, что его можно использовать, я бы не использовал UUID в качестве моего основного кластеризованного индекса / PK в большинстве случаев. При необходимости я бы, вероятно, сделал его второстепенным столбцом, возможно, индексированным, а может и нет.

Некоторые люди утверждают, что UUID можно использовать для безопасного создания / объединения записей из произвольного числа систем. Хотя UUID (в зависимости от метода), как правило, имеет астрономически малую вероятность столкновения, возможно - по крайней мере, с некоторым внешним вводом или очень неудача :) - генерировать столкновения. Я убежден, что между системами должна передаваться только true PK, что, я бы сказал, не является (или не должно быть) генерируемым базой данных *1014* UUID в большинстве случаев.

автоинкремент / ключи последовательности и таблицы последовательности

Это действительно зависит от того, что база данных поддерживает хорошо. Некоторые базы данных поддерживают последовательности, которые являются более гибкими, чем простое «автоинкремент». Это может быть или не быть желательным (или просто может быть единственным способом для такого рода задач). Таблицы последовательностей, как правило, еще более гибкие, но если нужна такая «гибкость», у меня возникнет соблазн вернуться к шаблону проектирования, особенно если он предполагает использование триггеров. Хотя мне не нравится «ограничение ORM», это также может иметь значение при выборе «более простых» типов автоинкремента или последовательности / поддержки базы данных.

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

Кроме того, я утверждаю, что «компрометация безопасности посредством предоставления автопоследовательности PK» является результатом неправильного предоставления свойства внутренней базы данных. Хотя это очень простой способ работы с CRUD, я полагаю, что существует различие между внутренними ключами и открытыми клавишами (например, красивым номером клиента).

Только мои два цента.

Редактировать , дополнительные ответы Тиму:

Я думаю, что сгенерированный против истинного ПК вопрос очень хороший, и я должен также рассмотреть его. Я бы хотел, чтобы UUID в целом соответствовал вашим замечаниям. Мое колебание было в размере против int / long. Не знал о потенциальной де-оптимизации индексации, что для меня гораздо важнее.

Я бы не стал беспокоиться о размере - если UUID лучше, то он лучше. Если это не так, то это не так. В общей схеме дополнительные 12 байтов по сравнению с int, скорее всего, не будут иметь большого значения. SQL Server 2005+ поддерживает функцию генерации UUID newsequentialid , чтобы избежать фрагментации, связанной с обычной генерацией UUID. На странице это обсуждается. Я уверен, что другие базы данных имеют аналогичные решения.

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

Да. Первичный ключ не должен быть единственным [уникальным] ограничением. Простое использование суррогатного PK не означает, что модель базы данных должна быть скомпрометирована :-) Дополнительные индексы также могут быть использованы для покрытия и т. Д.

И, говоря о «различии», вы говорите, что суррогатные первичные ключи никогда не просачиваются?

Формулировка в моем первоначальном посте была довольно сложной. Это не «никогда», а «если они делают , и это имеет значение , тогда это другая проблема». Часто люди жалуются на ненадежность через предположительные числа - например, если ваш заказ 23, то, скорее всего, есть заказ 22 и 24 и т. д. Если это ваша «защита» и / или может привести к утечке конфиденциальной информации, то система уже имеет недостатки. (Разделение внутренних и внешних идентификаторов по сути не решает эту проблему, и аутентификация / авторизация по-прежнему необходимы. Однако это одна проблема, возникающая при использовании «последовательных идентификаторов» - я считаю, что кодирование одноразового номера в распределенные URL-адреса обрабатывает это для моего вариант использования довольно неплохой.)

Больше к тому, что я действительно хотел донести : То, что суррогатный идентификатор PK равен 8942, не означает, что это порядок 8942. То есть соблюдение «некоторые поля являются только внутренними» для db "design" порядок "number" может быть совершенно не связан на поверхности (но полностью поддерживается в модели DB), например, "# 2010-42c" или что-либо еще, что имеет смысл для бизнес-требований. Именно этот внешний номер должен быть выставлен в большинстве случаев.

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

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

Конечно, как и во всем, оставайтесь открытыми и приспосабливайте модель к проблеме, а не к модели :-) Для такой службы, как твиттер, например, они используют свою собственную схему генерации чисел. См. Новое поколение твиттеров . В отличие от [некоторого] генерации UUID, подход с помощью твиттера (при условии, что все серверы настроены правильно) гарантирует , что ни один из распределенных машин / процессов никогда не сгенерирует дублирующийся идентификатор, требует только 64-бит, и поддерживает грубое упорядочение (наиболее значимые биты - метка времени). (Количество записей, созданных твиттером, никоим образом не связано с местными требованиями; -)

Счастливого кодирования.

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