SQL Server - это PK на основе GUID, наилучшая практика для поддержки горизонтального разбиения на основе клиента - PullRequest
7 голосов
/ 27 октября 2011

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

Некоторые грубые числа в базе данных ..

Общее количество арендаторов составит около 10 000.Объем данных, хранящихся на одного арендатора, варьируется от 500 МБ до 3 ГБ.Число арендаторов начнется с малого и увеличится до 10000 в течение нескольких лет, поэтому изначально мы можем начать с одной базы данных с несколькими арендаторами, но в более долгосрочной перспективе это потребуется для горизонтального масштабирования в целях повышения производительности.

Обновление - усложняющим фактором является то, что иногда арендаторы (компании) могут объединяться, и мне также необходимо поддерживать это ...,

Мульти-аренда будет реализована с использованием общей базы данных,Архитектура общей схемы, как описано в этой статье http://msdn.microsoft.com/en-us/library/aa479086.aspx

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

Я знаю, что использование GUID приводит к снижению производительности, поскольку основной ключ - это компромисс, который мне просто нужно принять?Есть ли другой способ проектирования горизонтального разбиения в будущем?

Вот пример - скажем, я хочу объединить компании с арендаторами 100 и 200 в будущем, если PK является целым числом, может бытьстолкновение, когда я копирую строки из базы данных 2 в базу данных 1, с {guids} я гарантирую, что столкновения не будет ...

база данных 1 база данных 2 tenantid, id, описание tenantid, id, description 100,1, 'foo' 200, 1, 'xxx' 100, 2, 'boo' 200, 2, 'yyy'

база данных 1 база данных 2 tenantid, id, описание tenantid, id, описание 100, {aaa}, 'foo' 200, {ccc}, 'xxx' 100, {bbb}, 'boo' 200, {ddd}, 'yyy'

Ответы [ 3 ]

9 голосов
/ 27 октября 2011

Идентификаторы GUID могут показаться естественным выбором для вашего первичного ключа - и, если вам действительно необходимо, вы, вероятно, можете поспорить, чтобы использовать его для ОСНОВНОГО КЛЮЧА таблицы. я бы настоятельно не рекомендовал использовать столбец GUID в качестве ключа кластеризации , что SQL Server делает по умолчанию, если вы специально не запретите.

Вам действительно нужно разделить две проблемы:

1) первичный ключ - это логическая конструкция - один из ключей-кандидатов, который однозначно и надежно идентифицирует каждую строку в вашей таблице.На самом деле это может быть что угодно - INT, GUID, строка - выберите то, что наиболее подходит для вашего сценария.

2) ключ кластеризации (столбец или столбцы, определяющие«кластеризованный индекс» в таблице) - это физическая вещь, связанная с хранилищем, и здесь маленький, стабильный, постоянно увеличивающийся тип данных - ваш лучший выбор - INT или BIGINT в качестве варианта по умолчанию.

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

Как и Кимберли Трипп - королева индексации - и другие много раз заявляли - GUID, поскольку ключ кластеризации не является оптимальным, поскольку из-за его случайности он приведетк массовой фрагментации страниц и индексов и в целом к ​​плохой производительности.

Да, я знаю - в SQL Server 2005 и более поздних версиях newsequentialid(), но даже это не совсем и полностью последовательно и, следовательно, также страдает от того жепроблемы, связанные с идентификатором GUID - чуть менее заметно.

Затем следует рассмотреть еще одну проблему: ключ кластеризации в таблице будет добавлен к каждой записи в каждом некластеризованном индексе вашей таблицы.также - таким образом, вы действительно хотите убедиться, что он как можно меньше.Как правило, INT с 2+ миллиардами строк должно быть достаточно для подавляющего большинства таблиц - и по сравнению с GUID в качестве ключа кластеризации вы можете сэкономить сотни мегабайт хранилища на диске и в памяти сервера.

Быстрый расчет - с использованием INT и GUID в качестве основного и ключа кластеризации:

  • Базовая таблица с 1 000 000 строк (3,8 МБ против 15,26 МБ)
  • 6 некластеризованных индексов (22,89 МБ против 91,55 МБ)

ИТОГО: 25 МБ против 106 МБ - и это только на одной таблице!

Еще немного пищи для размышлений - отличный материал от Кимберли Триппа - прочитайте его, прочитайте еще раз, переварите!Это действительно Евангелие для индексирования SQL Server.

Марк

4 голосов
/ 27 октября 2011

Здесь следует отметить 2 вещи:

  1. определение набора строк арендатора во всех строках
  2. определение строки в строках арендатора во всех строках

Точка 2 является первичным ключом.

Использование GUID для идентификации арендатора полезно, потому что вы не можете угадать столбец идентификатора другого арендатора (например, если вы используете IDENTITY согласно этому техническому документу).Но GUID для кластеризованного ключа - плохая идея (согласно ответу marc_s).

Это приводит к составному PK GUID и столбцу IDENTITY, вероятно

  • IDENTITYсначала как уникальный кластеризованный индекс,
  • GUID является FK таблицы арендатора, некластеризованного индекса
  • и PK в обоих столбцах, но не кластеризованных

Это должен быть разумный компромисс для охвата большинства шаблонов запросов и FK этой таблицы.

Конечно, это зависит от окончательного варианта: я предположил, что это некий «факт» илитаблица "родитель фактов"

3 голосов
/ 27 октября 2011

Рассматривали ли вы вместо этого федерации SQL Azure? Горизонтальное горизонтальное разбиение, которое включает в себя поддержку для перебалансировки операций «из коробки» (т. Е. Перемещение арендаторов между разделами), а также решение для обеспечения высокой доступности, предоставляемое сервисом. просто нет ничего похожего на коробочный продукт SQL Server. См. Представление федерации в SQL Azure или Как использовать Shard с SQL Azure .

Что касается вопроса о том, чтобы каждый объект PK был GUID, я действительно не вижу в этом смысла. Присвоение каждой таблице данных арендатора идентификатора клиента - да, безусловно. При создании кластеризованного индекса для всех данных арендатора в качестве крайней левой клавиши указывается tenantId: (tenantId, key, key, key)): ditto, must. Создание первичного ключа объекта будет (tenantId, entityId): очень вероятно. Но что делает entityId гидом? Я действительно не понимаю, почему. Если у вас нет сущностей , совместно используемых между арендаторами, tenantId действует как пространство имен, к которому применяется entityId. Перемещение данных через осколки в порядке, , даже если это приводит к дублированию entityId значений , поскольку объекты PK ограничены tenantId.

...