Вопрос

Мы работаем над разработкой приложения, которое обычно представляет собой OLTP (подумайте:система закупок).Однако в этом случае, в частности, необходимо, чтобы некоторые пользователи были отключены от сети, поэтому им нужно иметь возможность загрузить БД на свой компьютер, работать с ней, а затем синхронизироваться обратно, как только они окажутся в локальной сети.

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

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

Это плохая идея по какой-то причине?Будет ли доступ к этим таблицам через ключ GUID медленным?

Был ли у вас опыт работы с такими системами?Как вы решили эту проблему?

Спасибо!
Дэниел

Это было полезно?

Решение

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

Вам следует позаботиться о читаемом человеком идентификаторе.Гайды не могут обмениваться людьми - можете ли вы представить попытку подтвердить номер вашего заказа по телефону, если это гайд?Таким образом, в автономном сценарии вам, возможно, все равно придется генерировать что-нибудь - например, идентификатор издателя (рабочей станции/пользователя) и некоторый порядковый номер, поэтому номер заказа может быть 123-5678 -.

Однако это может не удовлетворять бизнес-требованиям наличия последовательного номера.На самом деле нормативные требования могут оказывать влияние - некоторые правила (возможно, SOX) требуют, чтобы номера счетов были последовательными.В таких случаях может возникнуть необходимость сгенерировать своего рода номер проформы, который фиксируется позже, когда системы синхронизируются.Вы можете столкнуться с таблицами, имеющими OrderId (Guid), OrderNo (int), ProformaOrderNo (varchar) — могут возникнуть некоторые сложности.

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

Другие советы

@SqlMenace

Есть и другие проблемы с GUID, видите ли GUID не являются последовательными, поэтому вставки будут разбросаны повсюду, это приводит к разбиению страниц и фрагментации индекса.

Не правда. Первичный ключ! = кластерный индекс.

Если кластеризованный индекс представляет собой другой столбец (на ум приходит «inserted_on»), то вставки будут последовательными, и не произойдет разделения страниц или чрезмерной фрагментации.

Это очень хорошее использование GUID.Единственным недостатком будет небольшая сложность в работе с GUID над INT и небольшая разница в размерах (16 байт против 4 байтов).

Я не думаю, что что-то из этого имеет большое значение.

Будет ли доступ к этим таблицам через ключ GUID медленным?

Есть и другие проблемы с GUID, видите ли GUID не являются последовательными, поэтому вставки будут разбросаны повсюду, это приводит к разбиению страниц и фрагментации индекса.

В SQL Server 2005 MS представила NEWSEQUENTIALID(), чтобы исправить это, единственная проблема для вас может заключаться в том, что вы можете использовать NEWSEQUENTIALID только в качестве значения по умолчанию в таблице.

Вы правы, это старая проблема, и у нее есть два канонических решения:

  • Используйте уникальные идентификаторы в качестве первичного ключа.Обратите внимание: если вас беспокоит читаемость, вы можете использовать свой собственный уникальный идентификатор вместо использования GUID.Уникальный идентификатор будет использовать информацию о дате и машине для создания уникального значения.

  • Используйте составной ключ идентификатора «Актёр».Каждый пользователь получает числовой идентификатор актера, а ключи вновь вставленных строк используют идентификатор актера, а также следующий доступный идентификатор.Таким образом, если два актера вставят новую строку с идентификатором «100», ограничение первичного ключа не будет нарушено.

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

Обязательно используйте guid.comb — он позаботится об индексировании.Если после этого вы столкнетесь с проблемами производительности, вы в кратчайшие сроки станете экспертом по масштабированию.

Другая причина использования GUID — возможность рефакторинга базы данных.Допустим, вы решили применить полиморфизм, наследование или что-то еще к своей сущности «Клиенты».Теперь вы хотите, чтобы клиенты и сотрудники были производными от Person и чтобы они делили таблицу.Наличие действительно уникальных идентификаторов упрощает миграцию данных.Здесь нет последовательностей или целочисленных идентификационных полей, с которыми можно было бы бороться.

Я просто собираюсь указать тебе на Каково улучшение производительности Sequential Guid по сравнению со стандартным Guid?, в котором рассказывается о GUID.

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

Однако лично мне нравится ответ SGUID.

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

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

Серверной частью будет SQL Server 2005.
Логика внешнего интерфейса/приложения будет .Net.

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

Использование GUID сэкономило нам массу работы, когда нам приходилось объединять две базы данных в одну.

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

@Саймон,

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

для этого я бы начал присматриваться к SQL Server Compact Edition!Это помогает решить все ваши проблемы.

Архитектура хранения данных с SQL Server 2005 Compact Edition

Он специально разработан для

Полевые приложения (FFA).FFA обычно имеют один или несколько из следующих атрибутов:

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

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

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

Первая мысль, которая приходит в голову:Разве MS не разработала модель DataSet и DataAdapter для поддержки подобных сценариев?

Кажется, я читал, что MS изменила свою модель набора записей ADO на текущую модель DataSet, поэтому она отлично работает и в автономном режиме.И еще есть это Службы синхронизации для ADO.NET

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

Надеюсь это поможет.

@Portman По умолчанию PK == Кластерный индекс, создание ограничения первичного ключа автоматически создаст кластеризованный индекс, вам нужно указать некластеризованный индекс, если вы не хотите, чтобы он был кластеризован.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top