У меня есть несколько таблиц, единственными уникальными данными которых являются столбец uniqueidentifier (Guid). Поскольку гиды не являются последовательными (и они генерируются на стороне клиента, поэтому я не могу использовать newsequentialid ()), я создал непервичный некластеризованный индекс для этого поля идентификатора, вместо того, чтобы давать таблицам кластерный первичный ключ.
Мне интересно, каковы последствия для производительности при таком подходе. Я видел, как некоторые люди предлагали, чтобы таблицы имели автоматически увеличивающийся ("идентификатор") int в качестве кластеризованного первичного ключа, даже если он не имеет никакого значения, поскольку это означает, что ядро базы данных может использовать это значение для быстрого искать строку вместо использования закладки.
Моя база данных реплицируется слиянием на нескольких серверах, поэтому я уклонялся от столбцов identity int, поскольку они немного сложны для правильной репликации.
о чем ты думаешь? Должны ли таблицы иметь первичные ключи? Или нормально не иметь кластеризованных индексов, если нет разумных столбцов для индексации таким образом?





Я тоже всегда слышал, что автоматическое приращение int хорошо для производительности, даже если вы на самом деле его не используете.
Имея дело с индексами, вы должны определить, для чего будет использоваться ваша таблица. Если вы в первую очередь вставляете 1000 строк в секунду и не выполняете никаких запросов, то кластеризованный индекс снижает производительность. Если вы выполняете 1000 запросов в секунду, то отсутствие индекса приведет к очень плохой производительности. Лучше всего при настройке запросов / индексов использовать анализатор плана запросов и профилировщик SQL в SQL Server. Это покажет вам, где вы сталкиваетесь с дорогостоящим сканированием таблиц или другими блокаторами производительности.
Что касается аргумента GUID vs ID, вы можете найти в Интернете людей, которые придерживаются обоих. Меня всегда учили использовать GUID, если у меня нет действительно веской причины не делать этого. У Джеффа есть хороший пост, в котором рассказывается о причинах использования GUID: https://blog.codinghorror.com/primary-keys-ids-versus-guids/.
Как и в большинстве случаев, связанных с разработкой, если вы хотите улучшить производительность, нет единственного правильного ответа. Это действительно зависит от того, чего вы пытаетесь достичь и как вы реализуете решение. Единственный верный ответ - протестировать, протестировать и снова протестировать с использованием показателей производительности, чтобы убедиться, что вы достигли своих целей.
[Редактировать] @Matt, после дополнительных исследований дискуссии о GUID / ID я наткнулся на этот пост. Как я уже упоминал ранее, не существует истинно правильного или неправильного ответа. Это зависит от ваших конкретных потребностей в реализации. Но вот несколько довольно веских причин использовать GUID в качестве первичного ключа:
For example, there is an issue known as a "hotspot", where certain pages of data in a table are under relatively high currency contention. Basically, what happens is most of the traffic on a table (and hence page-level locks) occurs on a small area of the table, towards the end. New records will always go to this hotspot, because IDENTITY is a sequential number generator. These inserts are troublesome because they require Exlusive page lock on the page they are added to (the hotspot). This effectively serializes all inserts to a table thanks to the page locking mechanism. NewID() on the other hand does not suffer from hotspots. Values generated using the NewID() function are only sequential for short bursts of inserts (where the function is being called very quickly, such as during a multi-row insert), which causes the inserted rows to spread randomly throughout the table's data pages instead of all at the end - thus eliminating a hotspot from inserts.
Also, because the inserts are randomly distributed, the chance of page splits is greatly reduced. While a page split here and there isnt too bad, the effects do add up quickly. With IDENTITY, page Fill Factor is pretty useless as a tuning mechanism and might as well be set to 100% - rows will never be inserted in any page but the last one. With NewID(), you can actually make use of Fill Factor as a performance-enabling tool. You can set Fill Factor to a level that approximates estimated volume growth between index rebuilds, and then schedule the rebuilds during off-peak hours using dbcc reindex. This effectively delays the performance hits of page splits until off-peak times.
If you even think you might need to enable replication for the table in question - then you might as well make the PK a uniqueidentifier and flag the guid field as ROWGUIDCOL. Replication will require a uniquely valued guid field with this attribute, and it will add one if none exists. If a suitable field exists, then it will just use the one thats there.
Yet another huge benefit for using GUIDs for PKs is the fact that the value is indeed guaranteed unique - not just among all values generated by this server, but all values generated by all computers - whether it be your db server, web server, app server, or client machine. Pretty much every modern language has the capability of generating a valid guid now - in .NET you can use System.Guid.NewGuid. This is VERY handy when dealing with cached master-detail datasets in particular. You dont have to employ crazy temporary keying schemes just to relate your records together before they are committed. You just fetch a perfectly valid new Guid from the operating system for each new record's permanent key value at the time the record is created.
Прочтите GUID в качестве первичного ключа и / или ключа кластеризации и Место на диске дешевое - в этом суть НЕТ! Кимберли Трипп и многие другие ее прекрасные сообщения в блоге - она четко показывает, насколько плоха идея ключа кластеризации в столбце GUID. Кроме того, горячие точки - это миф, который давно развенчан - больше не проблема после SQL Server 6.5 ....
Очаровательный. Я рассмотрю вариант «разделения страниц и перестроения индекса», если производительность станет проблемой. Спасибо за это.
Первичный ключ служит трем целям:
Первые два можно указать разными способами, как вы уже сделали.
Третья причина хороша:
Первичный ключ не обязательно должен быть автоматически увеличивающимся числовым полем, поэтому я бы сказал, что было бы неплохо указать столбец guid в качестве первичного ключа.
Определенно не рекомендуется использовать столбец guid в качестве первичного ключа, потому что первичные ключи сгруппированы, а guid - случайны. Это означает, что каждый раз, когда вы вставляете новую строку, ваша таблица существенно реструктурируется на диске. Обычно люди советуют, чтобы первичные ключи были последовательными, постоянно растущими типами, чтобы каждая новая строка прикреплялась к концу таблицы.
Первичный ключ по умолчанию поддерживается кластеризованным индексом, но его можно удалить (кластеризованный индекс).
@MattHamilton re "... не рекомендуется использовать столбец guid в качестве первичного ключа, потому что первичные ключи сгруппированы, а идентификаторы случайны", чтобы преодолеть это, вы можете использовать функцию "newsequentialid ()" в SQL 2005/2008 edit: нашел необходимый Сообщение CodingHorror, который говорит об этом ;-)
Первичный ключ не обязательно должен быть автоматически увеличивающимся полем, во многих случаях это просто означает, что вы усложняете структуру своей таблицы.
Вместо этого первичный ключ должен быть минимальным набором атрибутов (обратите внимание, что большинство СУБД допускают составной первичный ключ), который однозначно идентифицирует кортеж.
С технической точки зрения, это должно быть поле, от которого все остальные поля в кортеже полностью функционально зависят. (Если это не так, вам может потребоваться нормализация).
На практике проблемы с производительностью могут означать, что вы объединяете таблицы и используете увеличивающееся поле, но я, кажется, припоминаю кое-что о том, что преждевременная оптимизация - зло ...
Просто прыгнул, потому что Мэтт меня немного наживал.
Вы должны понимать, что, хотя кластеризованный индекс по умолчанию ставится на первичный ключ таблицы, эти две концепции являются отдельными и должны рассматриваться отдельно. CIX указывает способ, которым данные хранятся и на которые ссылаются NCIX, тогда как PK обеспечивает уникальность для каждой строки, чтобы удовлетворить ЛОГИЧЕСКИЕ требования таблицы.
Таблица без CIX - это просто куча. Таблица без ПК часто считается «не таблицей». Лучше всего понимать концепции PK и CIX по отдельности, чтобы вы могли принимать разумные решения при проектировании базы данных.
Роб
Никто не ответил на актуальный вопрос: каковы плюсы / минусы таблицы с NO PK ИЛИ КЛАСТЕРИРОВАННЫМ индексом. На мой взгляд, если вы оптимизируете более быстрые вставки (особенно инкрементную массовую вставку, например, когда вы массово загружаете данные в непустую таблицу), такая таблица: без кластерного индекса, без ограничений, без внешних ключей, без значений по умолчанию и НЕТ Первичный ключ в базе данных с простой моделью восстановления - лучший вариант. Теперь, если вы когда-нибудь захотите запросить эту таблицу (а не сканировать ее полностью), вы можете добавить некластеризованные неуникальные индексы по мере необходимости, но сведите их к минимуму.
На самом деле это неправильный - как ясно показывает Кимберли Трипп (королева индексирования): наличие кластерного индекса хороший приведет к увеличивать производительности INSERT! sqlskills.com/BLOGS/KIMBERLY/post/…
Я бы не назвал это четко показом :) Она говорит об общих принципах, не подкрепляя свое утверждение, ну, ничем, в то время как я говорю об очень конкретном сценарии, с которым я столкнулся в своей практике: массовые вставки потенциально сотен миллионы записей в непустую таблицу, которая затем никогда не обновляется и не используется в режиме произвольного чтения, а только сканируется полностью. Я полагаю, что здесь может быть больше факторов, чем индексов. Всегда проверяйте свои оптимизации, дети.
Поскольку вы выполняете репликацию, от вашей правильной личности следует держаться подальше. Я бы сделал ваш GUID первичным ключом, но некластеризованным, поскольку вы не можете использовать newsequentialid. Это кажется мне вашим лучшим курсом. Если вы не сделаете его ПК, а разместите на нем уникальный индекс, рано или поздно это может привести к тому, что люди, обслуживающие систему, не поймут взаимосвязи FK и правильно внесут ошибки.
Поскольку вы выполняете репликацию, от вашей правильной личности следует держаться подальше. Я бы сделал ваш GUID первичным ключом, но некластеризованным, поскольку вы не можете использовать newsequentialid. Это кажется мне вашим лучшим курсом. Если вы не сделаете его ПК, а разместите на нем уникальный индекс, рано или поздно это может привести к тому, что люди, обслуживающие систему, не поймут взаимосвязи FK и правильно внесут ошибки.