Какова наилучшая стратегия первичного ключа для многопользовательского мобильного / автономного мобильного приложения с базой данных SQLite и Azure SQL в качестве центрального хранилища?

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

десятки тысяч пользователейнесколько клиентов на пользователя (телефон, планшет, компьютер)миллионы строк в таблице (постоянно растут)

Azure SQL будет центральным хранилищем данных, которое будет доступно через веб-API. В число клиентов войдут веб-приложение и ряд нативных приложений, включая iOS, Android, Mac, Windows 8 и т. Д. Веб-приложение будет требовать подключения «всегда включено» и не будет иметь локального хранилища данных, а вместо этого будет получать и обновлять через API - думаю, CRUD через RESTful API.

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

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

Вот что мы рассмотрели до сих пор:

GUID

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

тождественность

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

композитный

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

HiLo (объединенный композит)

Как и в случае составного подхода, каждому клиенту при первой синхронизации назначается идентификатор клиента (int32). Идентификатор клиента объединяется с уникальным локальным идентификатором (int32) в один столбец, чтобы создать уникальный идентификатор для всего приложения (int64). Это должно привести к отсутствию конфликтов во время синхронизации. Хотя эти ключи имеют больший порядок, чем идентификаторы GUID, поскольку идентификаторы, генерируемые каждым клиентом, являются последовательными, будут тысячи уникальных идентификаторов клиентов, поэтому мы все еще рискуем фрагментироваться в нашем кластерном индексе?

Мы что-то упускаем? Есть ли другие подходы, которые стоит изучить? Обсуждение плюсов и минусов каждого подхода было бы весьма полезно.

Ответы на вопрос(1)

Ваш ответ на вопрос