Уникальные идентификаторы для пользователей

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

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

Кто-нибудь знает решение?

Спасибо

9 ответов

Решение

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

Когда у вас внезапно появятся миллионы пользователей, вы можете подумать об их изменении.

Другими словами, решить проблему, когда она у вас есть. "преждевременная оптимизация - корень всего зла".

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

Стандартное решение здесь - использовать GUID. Однако они не будут работать так же хорошо с точки зрения индексации.

Идентификаторы GUID хороши, но могут столкнуться (хотя и редко).

Это может быть нестандартное решение, но я собираюсь выкинуть его туда:

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

Допустим, у вас есть 3 сервера. Запишите идентификаторы следующим образом:

Сервер 1: 0 - 9,999,999
Сервер 2: 10000 000 - 19 999 999
Сервер 3: 20 000 000 - 29 999 999

Даже в пределах ограничений 32-битного int это должно оставить много места для расширения (может даже использовать пробелы в 100 000 000, если вы беспокоитесь), и это, по сути, гарантирует уникальность всей системы.

Если вам нужны миллионы идентификаторов и много узлов, сделайте первичный ключ составным из:

NodeID  int   --unique for each node 2 or 4 byte  
UserID  int   --auto increment 8 byte, repeats for each node

что намного лучше, чем GUID (меньше, использует меньше памяти и будет быстрее)

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

Вы можете использовать GUIDS. Но 5 миллионов - ничто с точки зрения данных и, вероятно, не потребует изменений. У нас более 10 000 000 разных людей в нашей системе, и у нас есть только база данных среднего размера, без разметки и без необходимости использования GUID.

GUID - это простой выход, но...

Насколько распределенным это должно быть? Если это ограниченное количество баз данных, вы можете дать каждой базе данных диапазон номеров для использования. Так, например, первая база данных автоматически генерирует числа в диапазоне от 0 до 999 999, а следующая использует от 1 000 000 до 1 999 999. Таким образом, каждый из них может генерировать идентификатор пользователя, не сталкиваясь друг с другом. Если база данных содержит уникальный номер, идентифицирующий ее, то диапазоны могут быть сгенерированы автоматически из этого номера.

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

GUIDs являются мусором в качестве ключей при кластеризации. Если нет кластеризации, вам все равно понадобится кластеризованный индекс для другого столбца.

Используйте целочисленный ключ и для каждого new узел / сайт

  • Шаг с шагом 10. Когда вы добавляете узлы, просто начните с 2, 3 и т. Д.
  • Используйте диапазоны, например, 1-> 1000000, 1000000 -> 1999999 и т. Д.
  • И не забудь -ве тоже. Например, вы можете иметь IDENTITY (-1,-1) для второго узла

Если у вас есть узлы / сайты, тогда будет работать и второй столбец с SiteID.

Если вы используете MSSQL, вы можете создать PK вашей таблицы как UNIQUEIDENTIFIER и установить для значения по умолчанию или привязки значение NEWID().

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

Особенно, если у вас есть несколько таблиц, и между ними существуют отношения, не рассматривайте Guids как первичный ключ.

Есть следующие два решения, которые я бы порекомендовал.

  1. если вы можете создать составные ключи, которые будут идеальными, как если бы это было банковское программное обеспечение, тогда это может быть BranchId, транзакция станет первичным ключом, где branchId - это идентификатор узла, вставляющего запись, а транзакция - автоматический номер в филиале, так что вы получите уникальность. весь путь.

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

Я понимаю, что второе решение немного запутанно и сложно, но все же лучше, чем использовать Guids в качестве PK. но если решение 1 применимо, пойти на это.

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

С уважением Мубашар

Другие вопросы по тегам