Уникальный идентификатор (guid) в качестве первичного ключа в дизайне базы данных
Наши данные хранятся в базе данных SQL Server 2008, между таблицами будет много запросов и стыков. У нас есть этот аргумент внутри команды, некоторые утверждают, что использование целочисленного идентификатора лучше для производительности, некоторые аргументируют использование guid (уникальный идентификатор).
Неужели производительность действительно страдает от плохого использования GUID в качестве первичного ключа?
Ответы
Ответ 1
128-битный ключ GUID (uniqueidentifier
), конечно, в 4 раза больше, чем 32-разрядный ключ int
. Однако есть несколько ключевых преимуществ:
- Нет проблемы с идентификацией IDENTITY INSERT при объединении содержимого
- Если вы используете значение COMB вместо NEWSEQUENTIALID(), вы получаете "свободную" временную метку INSERT. Вы можете даже
SELECT
из первичного ключа на основе диапазона даты/времени, если хотите, с несколькими причудливыми вызовами CAST()
.
- Они уникальны во всем мире, и теперь это довольно удобно.
- Поскольку нет необходимости отслеживать отметки с высоким уровнем воды, ваш уровень BL может назначить значение, а не SQL Server, тем самым устраняя шаг
SELECT scope_identity()
, чтобы получить первичный ключ после вставки.
- Если вы даже отдаленно можете иметь более 2 миллиардов записей, вам нужно использовать
bigint
(64 бит) вместо int
. Как только вы это сделаете, uniqueidentifier
будет в два раза больше, чем bigint
.
- Использование GUID делает безопасным раскрывать ключи в URL-адресах и т.д., не подвергая себя атакам "угадать-идентификатор".
- Между тем, как SQL Server загружает страницы с диска и как процессоры теперь в основном 64-битные, просто потому, что число составляет 128 бит вместо 32, это не значит, что для сравнения требуется 4 раза. Последний тест, который я видел, показал, что GUID почти так же быстро.
- Размер индекса зависит от того, сколько столбцов включено. Несмотря на то, что сами GUID больше, дополнительные 8 или 12 байтов могут быть незначительными по сравнению с другими столбцами в индексе.
В конце концов, выдавливание небольшого преимущества производительности с помощью целых чисел может не стоить потерять преимущества GUID. Протестируйте его эмпирически и решите для себя.
Лично я все еще использую оба варианта, в зависимости от ситуации, но решающий фактор никогда не снижался до производительности в моем случае.
Ответ 2
Я использую INT IDENTITY
для большинства своих основных и кластеризующих ключей.
Вам нужно разделить первичный ключ , который является логической конструкцией - он однозначно идентифицирует ваши строки, он должен быть уникальным и стабильным и NOT NULL
. GUID хорошо работает и для первичного ключа, поскольку он гарантированно уникален. GUID в качестве основного ключа является хорошим выбором, если вы используете репликацию SQL Server, так как в этом случае вам нужен уникальный идентификационный столбец GUID.
Клавиша в SQL Server - это физическая конструкция, которая используется для физического упорядочения данных и намного сложнее получить право. Как правило, Королева Индексации на SQL Server, Кимберли Трип, также требует, чтобы хороший ключ кластеризации был uniqe, стабильным, как можно более узким и в идеале постоянно увеличивающимся (все из которых a INT IDENTITY
).
См. ее статьи по индексированию здесь:
а также см. Jimmy Nilsson Стоимость GUID в качестве основного ключа
GUID - это ужасно плохой выбор для ключа кластеризации, поскольку он является широким, полностью случайным и, следовательно, приводит к плохой фрагментации индекса и низкой производительности. Кроме того, строки (-и) кластеризации также хранятся в каждой записи каждого некластеризованного (дополнительного) индекса, поэтому вы действительно хотите сохранить его маленьким - GUID равен 16 байт против INT 4 байт и с несколькими некластеризованными индексами и несколькими миллионами строк, это делает ОГРОМНОЕ различие.
В SQL Server ваш первичный ключ по умолчанию - ваш ключ кластеризации, но это необязательно. Вы можете легко использовать GUID в качестве своего первичного ключа с некластеризованным ключом и INT IDENTITY
в качестве ключа кластеризации - он просто немного осознает это.
Ответ 3
Отличная статья об этом, что у меня есть в моих закладках: http://blogs.msdn.com/b/sqlserverfaq/archive/2010/05/27/guid-vs-int-debate.aspx
Ответ 4
Большая проблема с GUID в качестве основных ключей заключается в том, что они вызывают массированную фрагментацию таблицы, что может быть большой проблемой производительности (чем больше таблица, тем больше проблема). Даже в качестве ключа для некластеризованного индекса они будут вызывать фрагментацию индекса.
Вы можете частично устранить проблему, установив соответствующий коэффициент заполнения, но это все равно будет проблемой.
Разница в размерах не сильно меня беспокоит, за исключением таблиц с другими узкими строками, в которых также требуются сканирование таблицы. В этих случаях возможность установки большего количества строк на страницу БД является преимуществом производительности.
При использовании GUID могут быть веские причины, но также есть и стоимость. Обычно я предпочитаю INT IDENTITY для первичных ключей, но я не избегаю GUID, когда они являются лучшим решением.
Ответ 5
Основным преимуществом использования GUID является то, что они уникальны во всем пространстве и времени.
Основным недостатком использования GUID в качестве ключевых значений является то, что они BIG. В 16 байт поп, они являются одним из самых больших типов данных в SQL Сервер. Индексы, построенные на GUID, будут больше и медленнее, чем индексы, построенные на столбцах IDENTITY, которые обычно являются ints (4 байта).
Таким образом, они являются хорошим решением для случаев, когда вам необходимо объединить данные из нескольких источников.
Источник: http://www.sqlteam.com/article/uniqueidentifier-vs-identity
Ответ 6
Если записи таблицы базы данных могут вырасти до миллиона записей, я думаю, что это не очень хорошая идея использовать ее в качестве первичного ключа.