Подтвердить что ты не робот

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

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

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

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

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

4b9b3361

Ответ 1

UUID,

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

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

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

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

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

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

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

Изменить, дополнительные ответы на Tim:

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

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

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

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

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

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

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

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

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

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

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