Вопрос

У меня есть несколько таблиц, единственными уникальными данными которых являются столбцы uniqueidentifier (Guid).Поскольку направляющие не являются последовательными (и они генерируются на стороне клиента, поэтому я не могу использовать newsequentialid()), я создал неосновной, некластеризованный индекс для этого поля идентификатора, вместо того, чтобы присваивать таблицам кластеризованный первичный индекс. ключ.

Мне интересно, каковы последствия этого подхода для производительности.Я видел, как некоторые люди предлагали, чтобы таблицы имели автоматически увеличивающийся («идентичность») int в качестве кластеризованного первичного ключа, даже если он не имеет никакого смысла, поскольку это означает, что механизм базы данных сам может использовать это значение для быстрого найдите строку вместо использования закладки.

Моя база данных реплицируется слиянием на нескольких серверах, поэтому я избегал использования столбцов Identity Int, так как с ними сложно справиться при репликации.

Что ты думаешь?Должны ли таблицы иметь первичные ключи?Или можно не иметь кластеризованных индексов, если нет разумных столбцов для индексации таким образом?

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

Решение

Имея дело с индексами, вы должны определить, для чего будет использоваться ваша таблица.Если вы в основном вставляете 1000 строк в секунду и не выполняете никаких запросов, то кластеризованный индекс снижает производительность.Если вы выполняете 1000 запросов в секунду, отсутствие индекса приведет к очень плохой производительности.Лучшее, что можно сделать при настройке запросов/индексов, — это использовать анализатор плана запроса и профилировщик SQL в SQL Server.Это покажет вам, где вы сталкиваетесь с дорогостоящим сканированием таблиц или другими блокировщиками производительности.

Что касается аргумента GUID против ID, в Интернете можно найти людей, которые поддерживают оба варианта.Меня всегда учили использовать GUID, если только у меня нет веских причин не делать этого.У Джеффа есть хороший пост, в котором рассказывается о причинах использования GUID: https://blog.codinghorror.com/primary-keys-ids-versus-guids/.

Как и в большинстве случаев, связанных с разработкой, если вы хотите повысить производительность, не существует единственного правильного ответа.Это действительно зависит от того, чего вы пытаетесь достичь и как вы реализуете решение.Единственный верный ответ — тестировать, тестировать и еще раз тестировать показатели производительности, чтобы убедиться, что вы достигаете своих целей.

Редактировать] @matt, после проведения еще некоторых исследований о дебатах GUID/ID, которые я наткнулся на этот пост.Как я уже упоминал ранее, не существует правильного или неправильного ответа.Это зависит от ваших конкретных потребностей в реализации.Но есть несколько вполне веских причин использовать GUID в качестве первичного ключа:

Например, существует проблема, известная как «горячая точка», когда определенные страницы данных в таблице находятся в зоне относительно высокой конкуренции за валюту.По сути, происходит следующее: большая часть трафика таблицы (и, следовательно, блокировок на уровне страницы) приходится на небольшую область таблицы, ближе к концу.Новые записи всегда будут поступать в эту точку доступа, поскольку IDENTITY — это генератор последовательных чисел.Эти вставки вызывают затруднения, поскольку требуют эксклюзивной блокировки страницы, на которую они добавляются (горячая точка).Это эффективно сериализует все вставки в таблицу благодаря механизму блокировки страниц.NewID(), с другой стороны, не страдает от горячих точек.Значения, сгенерированные с помощью функции NewID(), являются последовательными только для коротких пакетов вставок (когда функция вызывается очень быстро, например, во время вставки нескольких строк), что вместо этого приводит к случайному распределению вставленных строк по страницам данных таблицы. всего в конце - тем самым исключив хотспот из вставок.

Кроме того, поскольку вставки распределяются случайным образом, вероятность разделения страниц значительно снижается.Хотя разделение страницы здесь и там не так уж и плохо, эффект быстро складывается.При использовании IDENTITY коэффициент заполнения страницы совершенно бесполезен в качестве механизма настройки, и его с таким же успехом можно установить на 100% — строки никогда не будут вставлены ни на одну страницу, кроме последней.С помощью NewID() вы действительно можете использовать коэффициент заполнения как инструмент повышения производительности.Вы можете установить коэффициент заполнения на уровне, приблизительно соответствующем предполагаемому росту объема между перестроениями индекса, а затем запланировать перестроения в непиковые часы с помощью переиндексации dbcc.Это эффективно задерживает снижение производительности при разделении страниц до наступления непикового времени.

Если ты даже думать вам может потребоваться включить репликацию для рассматриваемой таблицы - тогда вы также можете сделать PK уникальным идентификатором и пометить поле guid как ROWGUIDCOL.Для репликации потребуется поле gui с уникальным значением с этим атрибутом, и оно будет добавлено, если его не существует.Если подходящее поле существует, то будет использовано только то, что есть.

Еще одним огромным преимуществом использования GUID для ПК является тот факт, что значение действительно гарантированно уникально, а не только среди всех значений, генерируемых этот сервер, но все значения, сгенерированные все компьютеры — будь то сервер базы данных, веб-сервер, сервер приложений или клиентский компьютер.Практически каждый современный язык теперь имеет возможность генерировать действительный guid - в .NET вы можете использовать System.Guid.NewGuid.Это ОЧЕНЬ удобно, в частности, при работе с кэшированными наборами данных master-detail.Вам не нужно использовать сумасшедшие схемы временного шифрования только для того, чтобы связать свои записи вместе, прежде чем они будут зафиксированы.Вы просто получаете совершенно действительный новый Guid из операционной системы для значения постоянного ключа каждой новой записи во время создания записи.

http://forums.asp.net/t/264350.aspx

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

Первичный ключ служит трем целям:

  • указывает, что столбцы должны быть уникальными
  • указывает, что столбец(и) должен быть ненулевым
  • задокументировать намерение, что это уникальный идентификатор строки

Первые два можно указать разными способами, как вы уже это сделали.

Третья причина хорошая:

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

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

Просто вступаю, потому что Мэтт меня немного подзадорил.

Вы должны понимать, что хотя кластерный индекс по умолчанию помещается в первичный ключ таблицы, эти две концепции различны и их следует рассматривать отдельно.CIX указывает способ хранения данных и обращения к ним в NCIX, тогда как PK обеспечивает уникальность каждой строки для удовлетворения ЛОГИЧЕСКИХ требований таблицы.

Таблица без CIX — это просто куча.Стол без ПК часто считают «не столом».Лучше всего получить представление о концепциях PK и CIX по отдельности, чтобы вы могли принимать разумные решения при проектировании базы данных.

Роб

Никто не ответил на актуальный вопрос:каковы плюсы/минусы таблицы без НИКАКОГО ПК НИ КЛАСТЕРНОГО индекса.По моему мнению, если вы оптимизируете более быстрые вставки (особенно инкрементальные массовые вставки, напримерпри массовой загрузке данных в непустую таблицу), такая таблица:БЕЗ кластерного индекса, БЕЗ ограничений, БЕЗ внешних ключей, БЕЗ значений по умолчанию и БЕЗ первичного ключа в базе данных с простой моделью восстановления является лучшим.Теперь, если вы когда-нибудь захотите запросить эту таблицу (вместо сканирования ее целиком), вы можете добавить при необходимости некластеризованные неуникальные индексы, но свести их к минимуму.

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

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

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

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

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

Поскольку вы выполняете репликацию, следует избегать вашей правильной личности.Я бы сделал ваш GUID первичным ключом, но некластеризованным, поскольку вы не можете использовать newssequentialid.Мне кажется, это твой лучший курс.Если вы не сделаете его PK, а присвоите ему уникальный индекс, рано или поздно это может привести к тому, что люди, которые обслуживают систему, не смогут правильно понять отношения FK, что приведет к ошибкам.

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