Производительность выбора первичного ключа - PullRequest
3 голосов
/ 29 марта 2012

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

Один из наших разработчиков считает, что, поскольку SQL внутренне хранит дату-время (Epoch?), DateTime является оптимальным PK для повышения производительности.

Я предложил создать составной ключ из 3 столбцов.,Повлияет ли это изменение ключа на производительность?

Было также предложено использовать GUID PK.Еще раз, производительность под вопросом.

Лучше ли переключиться на составной ключ?Если да, как мы можем решить / объяснить эти проблемы производительности?

1 Ответ

4 голосов
/ 29 марта 2012

Идентификаторы 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.

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

DATEITME сам по себе не кажется хорошей идеей для первичного ключа - в SQLСервер, DATETIME имеет точность 3,33 мс, поэтому в загруженной системе есть большая вероятность, что у вас будут неуникальные значения - не очень хорошая идея для ПК!

Если производительность - вашаПри этом я бы рекомендовал использовать один столбец INT IDENTITY (даже если это суррогатный столбец) для вашего уникального кластеризованного индекса первичного ключа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...