При использовании UUID, следует ли использовать AUTO_INCREMENT?

Мы создаем новое веб-приложение, которое будет иметь автономную версию приложения для iPad/Android на нескольких локальных устройствах, которые будут включать в себя вставки новых данных. Поэтому мы требуем использования UUID для обеспечения необходимой двухсторонней синхронизации с основной базой данных. Для этого мы будем хранить UUID в качестве первичного ключа BINARY(16).

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

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

Единственная проблема, которую я вижу в этом, заключается в том, что UUID необходимо использовать в качестве ссылки (используя ограничения внешнего ключа) для других таблиц (т.е. список проблем, связанных с проверкой, которая, в свою очередь, привязана к сайту, все из которых задействованы во вставках, и поэтому все они требуют UUID). Семантически, для первичного ключа более важно, чтобы ссылка была ссылкой, но в качестве распределенной системы мы не можем использовать для этого AUTO_INCREMENTS. Есть ли недостатки в использовании уникального (а не нулевого) индекса, а не первичного ключа для этих ссылок (и, конечно же, JOIN, который будет с ними)?

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

Edit:

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

Ответы

Ответ 1

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

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

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

Ответ 2

Когда у вас есть большой распределенный хранилище данных, если вы используете UUID или GUID как уникальный ключ и используете его позже, это не хорошо.

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

Поделитесь опытом нашего проекта как справочной. У нас есть 300 миллиардов записей, сохраненных в параллельном хранилище данных, в нашей системе автоматический инкрементный ключ даже не поддерживается. Мы используем 8 байтов bigint в качестве первичного ключа (на самом деле уникальный ключ в нашей системе также не поддерживается, но это не влияет на логическую уникальность), когда мы обрабатываем файл и файл загрузки, мы используем 3 байта для генерации идентификатора файла, который равен 2 ^ 24 файлов, нам нужно загрузить около 2000 файлов в день, поэтому 2 ^ 24 может поддерживать около 25 лет, если это не так.

Мы используем остальные 4 байта как идентификатор строки, который составляет 4 миллиарда строк, у нас нет 4 миллиардов строк в любом файле. Мы резервируем 1 байт. Во время обработки ETL нам нужно только отслеживать идентификатор файла в основной базе данных, которая поддерживает автоматический инкрементный идентификатор, когда нам нужно создать идентификатор записи при обработке файла, мы объединяем FileID + reserve 1 byte + 4 bytes rowID.

Ответ 3

Вы можете использовать составной первичный ключ, состоящий из автоматически увеличивающегося значения идентификатора bigint, назначенного автономным клиентом, плюс идентификатор bigint, назначенный клиенту. Таким образом, у вас будет запись 15, сделанная на клиенте 1235.

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