|
|
|
GUID or not GUID
|
|||
|---|---|---|---|
|
#18+
Доброго времени суток! Сразу извините за много текста и если подобный вопрос подымался, вроде ничего подобного не нашел в поиске. Итак, исходные данные: проектируется распределенная БД. Распределенность будет за счет как горизонтального масштабирования одной бд с взаимной merge репликацией между инстансами, там и за счет существования нескольких БД с данными разных подсистем одной большой системы, которые (данные), возможно, будут между собой переплетаться связями (есть БД заказов и БД клиентов. В заказе будет ссылка на клиента). Также необходимо производить обновление неконтролируемых установок нашей системы новыми версиями, в которых могут идти предустановленные нами данные, которые также могут добавляться/изменяться нами, т.е. id записи должны быть уникальными (см. "Вопрос"). Таргетинг: пока только MSSQL, PostgreSQL. Планируемый объем данных на таблицу - до 1-2 000 000. Больше - думаю будем партиционировать. Ввиду того, что данные должны быть уникально идентифицированы, пришел к выводу юзать sequential Guid (uniqueidentifier) для PK. Т.е. фрагментация индекса будет сравнимой с (BIG)INT, проблема только в увеличении объема таблицы/БД из-за Guid. После прочтения горы статей/форумов (сам я не DBA, но пытаюсь к этому также идти. Так что если вопросы глупые, не обезсутьте) понял, что кластерный индекс из Guid (даже последовательного) - зло, т.к., как минимум в MSSQL, некластерные индексы хранят запись кластерного индекса как ссылку на данные, т.е. при наличии множества FK, объем таких индексов/БД/потребления памяти сиквелом будет сильно-сильно расти. Советуют в этом случае делать Guid PK некластерным, а доп. поле INT identity кластерным для FK и (более быстрого) физического расположения страниц таблицы. Учитывая, что: 1) записи должны быть уникальными, для избежания гемора с п.2 и далее. 2) необходима merge репликация (с INT PK все равно будет добавлено Guid поле). 3) необходимо обновление клиентов новыми версиями с преустановленными нами данными (справочники и т.п.), которые могут как добавляться со статическими Id, там и редактироваться (существующие записи, нами). 4) данные в основном выбираются только по PK либо по другим полям, но не PK. вопросы: 1) правильно ли выбран GUID + некластерный PK? Не будет ли провалов производительности из некластерности (нужен еще hop по кластерному индексу до данных) при поиске по PK? 2) оправдано ли выделение отдельного INT identity поля для кластерного индекса (при наличии 2-4 FK на таблицу) как по скорости, так и по росту размера БД? По сути это поле будет холостое, не используемое нами напрямую. 3) можно ли реализовать по другому с учетом требований? Как варианты вижу: а) юзать INT для PK и для каждого сервера БД выделять свой диапазон значений. Проблемы: сервером может быть 1-N (будут добавляться с ростом нагрузки); это не решит проблемы обновления клиентов с нашими данными (id могут совпадать с клиентскими). б) юзать INT PK, но с методом распределения значения HiLo. Параметры всех PK будут лежать где-то на одном, центральном сервере, доступном всем другим. Так решиться проблема динамического добавления серверов, но опять таки, проблема обновления клиентов не решаема. Можно конечно выделить пул значений PK сугубо для нас и юзать их (значения) при поставке статических данных, но не известно, сколько данных мы будем поставлять (хватит ли пула через год/два), да и стремно как-то иметь ограниченность. По сути, т.к. мы сможем безболезненно масштабировать БД горизонтально, то замедление работы с данными из-за guid (больше данных, меньше таблиц в кеше сиквела и т.п.) может нивелироваться добавлением нового сервера(ов). Беспокоит только распухающие размеры БД. Вобщем, если кто-то реализовывал данный функционал или планирует или есть мысли, буду благодарен за обмен опытом. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.05.2011, 03:19 |
|
||
|
GUID or not GUID
|
|||
|---|---|---|---|
|
#18+
Остальная структура базы (кроме pk) известна? Почему бы не провести нагрузочный тест? Sequential guid не нужен. Одно из преимуществ guid - что его можно сгенерить на клиенте без лишнего запроса с сервера. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.05.2011, 05:27 |
|
||
|
GUID or not GUID
|
|||
|---|---|---|---|
|
#18+
Тесты проводили: на 1млн. записей скорость вставки и выборки Guid и int почти одинакова (небольшой разницей на таком объеме можно принебречь). Join`ы тоже практически идентичны, но это не под (паралельной) нагрузкой, что требует много времени для такого тестирования. Поэтому и пришел на форум, может кто уже сталкивался. Единственный минус - база пухнет при юзании guid в 3 раза больше и это даже без FK на эту таблицу. Sequential guid очень дажу нужен для кластерного индекса, иначе фрагментация зашкаливает. Т.к. скорость генерации последовательного и непосл. одинакова, а для послед. нужна только сетевая карта, которая есть на всех машинах, то лучше генерить последовательные, мало ли что потом будет и надо будет перевести в кластерный. Из преимуществ нас больше всего интересует уникальность в пределах системы. Кстати, генерить на клиенте можно не только guid. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.05.2011, 11:50 |
|
||
|
GUID or not GUID
|
|||
|---|---|---|---|
|
#18+
ARMSoft, закрыт с каким выводом? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.05.2011, 12:44 |
|
||
|
GUID or not GUID
|
|||
|---|---|---|---|
|
#18+
GUID - наименее геморойный вариант, но не оптимальный в нашем случае. Т.к. планируются большие вливания, БД будет неоправданно расти очень сильно (на 1млн. записей только в одной таблице только с PK разница в 3 раза по размеру (+100Мб в случае с GUID)). Плюс будет много баз (для LB) с реплицией между собой, что тоже скажеться на транспорте/IO... В итоге решили пойти путем диапазонов+HiLo. Может кому пригодиться данная выжимка: * ID PK CLUSTERED bigint. BIGINT - чтобы хватило диапазонов для последующих добавлений/разделений БД в кластер LB. Максимальное значение - 9,223,372,036,854,775,807. Из них первые (cлева) 5 цифр мы отдаем под уникальный номер БД (максимум 92233 баз/разделений и т.п. Думаю достаточно на наш век), остальное для знаений ID - 100 триллионов значений (почему так много см. ниже). * диапазоны будут выделяться статически (отдельная таблица со списком диапазонов и текущего значения), не через identity, для уменьшения нагрузки (раундтрипов) на БД + часто нужно знать значение ID до вставки записи. * значения идентификаторов будут выделяться по методу HiLo , что позволит исключить задвоение при конкуренции к одной БД и уменьшить нагрузку на БД. * при добавлении БД в кластер LB, этой БД дается уникальный диапазон, одинаковый (и отдельный) для каждой таблицы этой БД. Итого: * bigint будет не так расточителен и более (не сильно) быстр GUIDа. * уникальные диапазоны позволят без проблем реплицировать (с объединением) данные между любыми БД. * кол-ва значений в диапазоне хватит как на одну БД (на очеееень долгую жизнь), так для разделения (даже несколько раз) одной БД. Минусы архитектуры: * необходимость контроля непересечения диапазонов разных БД, если между ними нужна репликация или LB. Это решим собственным маленьким сервером(исом), который будет диап. хранить и выдавать новым инсталяциям в пределах компании, в том числе и распределенной. Следить конечно за таким сервером надо будет, как за золотом, это да. * нужно продумать recovery strategy. Для восстановления будем юзать бекапы, но нужно продумать ситуацию: бекап кадое утро, за вечером создавшиеся записи реплицировались другим БД и база-источник умерла. Восстановили с утреннего бекапа. Вопросы: 1) что делать с реплицированными записями на других БД? удалить? врят ли. Реплицировать назад? возможно, но т.к. мы восстановили значение ID на утро, могут быть пересечения. Короче, это пока оставшийся вопрос. Кто что думает? Какие камни мы не учли? зы: спорить по-поводу выбора bigint и диапазонов нет смысла, т.к. для нас это пока наиболее оптимально с учетом роста в будущем, т.к. переделывать уже законченную систему будет на порядки дороже. Интересуют мнения, какие бока могут еще вылезти при такой реализации. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.05.2011, 13:53 |
|
||
|
GUID or not GUID
|
|||
|---|---|---|---|
|
#18+
для меня бы остался главным вопрос "потребления" выделенных id - борьба и блокировки за получение следующего значения id ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.05.2011, 15:26 |
|
||
|
GUID or not GUID
|
|||
|---|---|---|---|
|
#18+
ARMSoft, фигня все это используйте гуид ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.05.2011, 15:44 |
|
||
|
GUID or not GUID
|
|||
|---|---|---|---|
|
#18+
spдля меня бы остался главным вопрос "потребления" выделенных id - борьба и блокировки за получение следующего значения id в чем хорош алгоритм HiLo, так это в малой вероятности блокировок. Есть Hi значение - множитель (размер шага если сравнивать с identity), а Lo - приращение относительно этого множителя. Смысл в том, что клиент резервирует себе пачку значений, блокируя данные с HiLo параметрами (обычно есть отдельная таблица в БД) только раз и постепенно расходует этот резерв. Потом резерв опять. Т.е., если выбрать размер Hi = 100, то обращение к БД будет раз на 100 идентификаторов (=новых объектов). Для нерасточительства мы выбрали Hi=10, что даже под нагрузкой будет не напряжно. ViPRosфигня все это. используйте гуид Для нас это был кандидат №1, но предполагаемые объемы данных и требования hi load real-time системы вносят свои коррективы. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.05.2011, 17:03 |
|
||
|
GUID or not GUID
|
|||
|---|---|---|---|
|
#18+
ARMSoftв чем хорош алгоритм HiLo, так это в малой вероятности блокировок. Есть Hi значение - множитель (размер шага если сравнивать с identity), а Lo - приращение относительно этого множителя. Смысл в том, что клиент резервирует себе пачку значений, блокируя данные с HiLo параметрами (обычно есть отдельная таблица в БД) только раз и постепенно расходует этот резерв. Потом резерв опять. Т.е., если выбрать размер Hi = 100, то обращение к БД будет раз на 100 идентификаторов (=новых объектов). Для нерасточительства мы выбрали Hi=10, что даже под нагрузкой будет не напряжно. Но на реализацию резервирования id необходимо реализовывать отдельный функционал и насколько я понимаю таких параллельных систем идентификации у вас несколько! Это в конечном итоге скажется на сложности системы и вносит потенциальный источник проблем... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.05.2011, 17:26 |
|
||
|
GUID or not GUID
|
|||
|---|---|---|---|
|
#18+
Реализация уже есть, одна для всех параллельных систем, кода 100 строк. С учетом использования этого всего в NHibernate, программеру даже думать на эту тему не нужно, т.е. человеческого фактора минимум. Логика простая: long hiValue = "select hi from ranges for update "; "update ranges set hi = (hiValue+1)" и дальше расходуем зарезервированный диапазон значений. Т.е. и легко и проблем нет. Главное следить за целостностью данных HiLo значений. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.05.2011, 17:38 |
|
||
|
GUID or not GUID
|
|||
|---|---|---|---|
|
#18+
ARMSoft, хе, если используете такое "средство" как хибернейт, то тем более гуид по сравнению с тем что генерирует он, все остальное меркнет а так дело хозяйское ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.05.2011, 18:03 |
|
||
|
GUID or not GUID
|
|||
|---|---|---|---|
|
#18+
ViPRosARMSoft, хе, если используете такое "средство" как хибернейт, то тем более гуид по сравнению с тем что генерирует он, все остальное меркнет а так дело хозяйское хм, за много лет проблем вроде не было, главное контролировать ситуацию. Бизнес логика, это в основном элементарный cruid. Все что сложнее, делается критериями, т.е. то, что он генерит зависит сугубо от кривости рук девелопера, не более. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.05.2011, 18:10 |
|
||
|
|

start [/forum/topic.php?fid=32&msg=37283463&tid=1542149]: |
0ms |
get settings: |
8ms |
get forum list: |
18ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
175ms |
get topic data: |
11ms |
get forum data: |
2ms |
get page messages: |
67ms |
get tp. blocked users: |
1ms |
| others: | 226ms |
| total: | 516ms |

| 0 / 0 |
