Существует ли альтернатива GUID для генерации распределенных ключей?

Моя ситуация:

  • У меня есть несколько клиентских приложений, в которых используется локальная БД (MS SQL, MS Access - извините, это система Enterprise, я должен поддерживать устаревшее...)
  • Я не знаю ничего о тренде среди клиентов - теперь он ~ 10, но он может быть ~ 100 в год.
  • Данные из этих таблиц поступают на мой центральный сервер и помещаются в одну общую таблицу.
  • Иногда существующие (клиентские) данные изменяются - мне приходится выполнять операции обновления/удаления
  • Я не хочу использовать GUID (.NET type System.Guid). Трудно просто реализовать и поддерживать в MS Access. Кроме того, не подходит для производительности
  • Мне нужен быстрый поиск в этой общей таблице, поэтому было бы неплохо использовать int или long int как PK

Итак, я хочу:

  • Что-то уникальное, чтобы избежать столкновений (он будет использоваться как ПК)
  • Должно быть, должно быть int или long int
  • Должна быть назначаемой клиентской стороной перед вставкой

Мое текущее решение - взять CRC из конкатенации:

  • ProcessodID
  • Дата биографии
  • Имя пользователя (строки, оборудование\связанные с пользователем данные)
  • DateTime.Now(UNC)

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

UPDATE: синхронизация между клиентом и сервером - это периодическое действие, поэтому оно может происходить 2-3 раза в день (это переменная конфигурации)

Ответ 1

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

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

Ответ 2

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

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

Ответ 3

Вы можете реализовать таблицу .

В принципе, таблица ключей - это всего лишь таблица с одной записью: следующий доступный целочисленный ключ. Когда вашей программе необходимо сгенерировать ключ, он увеличивает ключ в таблице ключей. Теперь он зарезервировал ранее доступный ключ. Он может назначить этот ключ тому, что ему нравится, и будет уверен, что он не будет конфликтовать с каким-либо другим ключом, потянутым таким же образом. Вот как работает LightSpeed ​​ORM. Его преимущество над использованием встроенного столбца идентификации заключается в том, что вы можете назначать идентификаторы элементов перед их вставкой в ​​базу данных, и поэтому они могут определять отношения элементов перед вставкой всех элементов одновременно.

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

Ответ 4

Просто используйте ключ int64, на стороне клиента используйте отрицательно увеличивающиеся числа от 0 (начиная с -1), а затем на стороне сервера после того, как синхронизация использует положительные инкрементные числа, когда вы синхронизируете данные с клиента на сервер вы просто возвращаете новые положительные номера сторон сервера. Я верю, что обновление ключа на записи достаточно просто, если нет, то просто удалите старый и вставьте новый со значениями.

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

Если вы мертвы против использования GUID (MSDN для System.Guid.NewGuid() указывает, что MAC-адрес как часть значения и сделать их очень уникальными), тогда вы отвечаете либо сложным ключом (и НЕ одним, основанным на crc сложного ключа!); Пожалуйста, не ошибайтесь, думая, что ваше решение CRC менее вероятно для столкновения, чем GUID, если у вас больше энтропии, чем у 128-битного GUID, вы только делаете больше работы для себя.

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

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

-5, -4, 76, 78, 79

что означает, что -4 и -5 необходимо вставить в центральное место, а затем обновить их до нового значения (вероятно, 80 и 81 в этом примере).

Если вы хотите продолжить чтение уникальности GUID и вероятность столкновения, я предлагаю вам прочитать Eric Lippert недавний блог сообщения в теме . А что касается стороны Access, вы можете просто .ToString() и преобразовать их в текстовый ключ. Но поскольку я представил решение, которое будет работать для пространства int/int64, это не требуется.