GUID / UUID для этого сценария?Или составной ключ?Или другой - PullRequest
3 голосов
/ 07 февраля 2011

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

Каждому «сайту» присваивается уникальный текстовый ключ (созданный человеком). Однако мысль о том, чтобы каждая таблица в дизайне базы данных ссылалась на ключ сайта, не очень привлекательна.

Вот пример очень урезанной версии схемы без , беспокоящейся об удаленной репликации (которая будет работать нормально для большинства клиентов): -

(для краткости я покажу только таблицу истории для таблицы Area):

[Site]
SiteKey [PK] (Gauranteed 100% unique across all sites text based key)

[User]
SiteKey [FK -> Site]
UserID [PK]

[Area]
SiteKey [FK -> Site]
AreaID [PK]
Description
UpdatedDtm
UpdatedUserID [FK -> User]

[AreaHistory]
Site [FK -> Site]
AreaID [FK -> Area]
Description
UpdatedDtm
UpdatedUserID [FK -> User]
AuditedDtm

[Location]
AreaID [FK -> Area]
LocationID [PK]
Description
UpdatedDtm
UpdatedUserID [FK -> User]

[Sensor]
LocationID [PK / FK -> Location]
SensorNo [PK]
UpdatedDtm
UpdatedUserID [FK -> User]

[Reading]
LocationID [PK / FK -> Sensor]
SensorNo [PK / FK -> Sensor]
ReadingDtm [PK]

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

Первый способ обдумать эту проблему - это сделать:

gs short):

[Location]
SiteKey [FK -> Location, FK -> User] ** ADDED THIS
AreaID [FK -> Area]
LocationID [PK]
Description
UpdatedDtm
UpdatedUserID [FK -> User]

[Sensor]
SiteKey [FK -> Location, FK -> User] ** ADDED THIS
LocationID [PK / FK -> Location]
SensorNo [PK]
UpdatedDtm
UpdatedUserID [FK -> User]

[Reading]
SiteKey [FK -> Sensor] ** ADDED THIS
LocationID [PK / FK -> Sensor]
SensorNo [PK / FK -> Sensor]
ReadingDtm [PK]

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

Альтернатива заключается в следующем (в некоторых местах используются UUID): -

[User]
SiteKey [FK -> Site]
UserUUID [PK]

[Area]
SiteKey [FK -> Site]
AreaUUID [PK]
Description
UpdatedDtm
UpdatedUserUUID [FK -> User]

[AreaHistory]
Site [FK -> Site]
AreaUUID [FK -> Area]
Description
UpdatedDtm
UpdatedUserUUID [FK -> User]
AuditedDtm

[Location]
AreaUUID [FK -> Area]
LocationUUID [PK]
Description
UpdatedDtm
UpdatedUserUUID [FK -> User]

[Sensor]
LocationUUID [PK / FK -> Location]
SensorNo [PK]
UpdatedDtm
UpdatedUserUUID [FK -> User]

[Reading]
LocationUUID [PK / FK -> Sensor]
SensorNo [PK / FK -> Sensor]
ReadingDtm [PK]

Помните, что это сокращено, но это иллюстрирует проблему.

Есть ли какие-то альтернативы, которые я могу упустить? Я думал о переназначении удостоверения личности, но это, казалось, вводило новые еще худшие кошмары.

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

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

Если это имеет какое-то значение, я использую PostgreSQL.

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

Ответы [ 4 ]

2 голосов
/ 11 февраля 2011

Я более или менее пришел к выводу, что ИМХО для этого сценария использование UUID является чем-то вроде «быстрого исправления», может быть, даже немного хаком. Я решил, что для меня, в данном случае, использование составного ключа является более чистым. Используя UUID, я с таким же успехом могу просто добавить SiteKey к каждому идентификатору.

1 голос
/ 11 февраля 2011

Я также добавлю еще один набор готовых ответов, о которых вы можете хотя бы подумать:

  1. Если вы хотите сохранить сайт как часть составного ключа в базовых данных - с помощью генерации кода, представлений и обновляемых триггеров (по крайней мере, на SQL Server), можно создать обновляемые представления, которые не не выставлен ключ сайта. Таким образом, вы можете скрыть это от уровня приложения (предполагается, что приложение не будет ориентировано на сайт).

  2. На самом деле не реплицируйте, а консолидируйте данные в базу данных отчетов и поместите сайт ТОЛЬКО на уровне отчетов. Конечно, ваша схема отличается, но она предназначена для отчетов, так что ей даже нужен тот же RI?

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

1 голос
/ 07 февраля 2011

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

0 голосов
/ 11 февраля 2011

Учитывая то, что вы сказали, я бы использовал GUID (и более склонен к этому при увеличении количества таблиц).Обратите внимание, что в SQL Server кластерный индекс хорошо использовать в узком увеличивающемся ключе, и часто это также первичный ключ, общий GUID не так эффективен, поскольку вызывает проблемы, связанные с невозрастающим характером.Существует NEWSEQUENTIALID (), который генерирует только последовательные GUID:

INT против уникального идентификатора для поля идентификатора в базе данных

Я использовал технику COMB ID, перед которойтакже была возможность извлечения даты и времени из GUID, что дает вам бесплатную временную метку создания (хотя и не обязательно бесплатную, поскольку она сама по себе не индексируется) (поскольку вы уже берете дополнительные байты для GUID по сравнению с int)

Я предполагаю, что некоторая или большая часть этой логики применима к postgressql, но что касается особенностей его индексации или реализации кластеризации / кучи, у меня нет прямого опыта.

...