Основные ключи SQL - PullRequest
       33

Основные ключи SQL

4 голосов
/ 07 апреля 2011

Итак, мы с коллегой спорим о том, как лучше генерировать первичные ключи, которые являются GUID.

Мы используем .NET 4.0 с сущностями 4 и используем хранимые процедуры для выбора/insert/updates.

Он хочет создать первичный ключ GUID в коде и передать его обратно как часть вставки, используя класс Guid или / и используя некоторый созданный класс Sequential GUID.

IЯ хочу, чтобы GUID создавался SQL Server при вставке с использованием newid () или newsequentialid ().

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

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

Итак, какой метод лучше подходит для одиночных вставок?Какой метод лучше использовать для нескольких вставок в транзакции?

Ответы [ 2 ]

12 голосов
/ 07 апреля 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 - чуть менее заметно.Если вы настаиваете на GUID, то по крайней мере используете newsequentialid() метод на сервере!

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

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

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

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

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

Марк

1 голос
/ 08 апреля 2011

Когда у меня возникают подобные вопросы, я говорю себе: «SQL Server хорош в наборах, поэтому позвольте ему делать то, что хорошо», а иногда «1 - это просто особый случай N».

Какой метод лучше для одного вставляет?

Время одной вставки будет одинаковым для любого из ваших подходов для синхронного вызова SQL. Однако «его» подход даст вам больше проблем со временем поиска по линии, потому что его последовательный метод guid не будет столь же хорошим как серверы sql (и вы, вероятно, потеряете глобальный уникальность). Это также разделит вашу кодовую базу, когда вам неизбежно потребуется сделать несколько вставок.

Какой метод лучше использовать для нескольких вставляет в транзакцию?

Если вы обсуждаете вставку на основе набора (insert / select) v.s. вставка одной строки (вставка в), основанная на множестве, выиграет на нескольких вставках, потому что возвращение к клиенту будет дорогой частью.

Если бы это был я, я бы создал SP, который принимает сериализованную коллекцию объектов для вставки, выполняет вставку / выборку с выходным предложением , проверяет «Пример B. Использование OUTPUT с идентичностью и вычисленные столбцы "на этой странице , пусть sql-сервер создаст GUID (если вы застряли на нем) и вернетесь к клиенту или выполните следующий оператор в SP, чтобы вставить дочерние строки на основе выходной таблицы вставка сгенерирована.

...