У меня есть приложение, которое использует GUID в качестве первичного ключа почти во всех таблицах, и я прочитал, что существуют проблемы с производительностью при использовании GUID в качестве первичного ключа. Честно говоря, я не видел никаких проблем, но я собираюсь запустить новое приложение, и я все еще хочу использовать GUID в качестве первичных ключей, но я думал об использовании составного первичного ключа (GUID и, возможно, другое поле .)
Я использую GUID, потому что ими удобно и легко управлять, когда у вас есть разные среды, такие как «производственная», «тестовая» и «dev» базы данных, а также для миграции данных между базами данных.
Я буду использовать Entity Framework 4.3 и хочу назначить Guid в коде приложения, прежде чем вставлять его в базу данных. (т.е. я не хочу, чтобы SQL генерировал Guid).
Какова наилучшая практика для создания Основных ключей на основе GUID, чтобы избежать предполагаемых падений производительности, связанных с этим подходом?
Ответы:
Идентификаторы GUID могут показаться естественным выбором для вашего первичного ключа - и, если вам действительно нужно, вы, вероятно, можете поспорить, чтобы использовать его для ПЕРВИЧНОГО КЛЮЧА таблицы. Что я настоятельно рекомендую не делать, так это использовать столбец GUID в качестве ключа кластеризации , что SQL Server делает по умолчанию, если вы специально не запретите это делать.
Вам действительно нужно держать в стороне две проблемы:
первичный ключ является логической конструкцией - один из ключей - кандидатов , которые однозначно и надежно идентифицируют каждую строку в таблице. Это может быть что угодно, на самом деле -
INT
,GUID
, строка - выбрать то , что делает большинство смысла для вашего сценария.ключ кластеризации (столбец или столбцы , которые определяют «кластерный индекс» на столе) - это физическое хранение связанных вещь, и здесь, небольшой, стабильный, постоянно увеличивающийся тип данных ваш лучший выбор -
INT
илиBIGINT
как ваш опция по умолчанию.По умолчанию первичный ключ в таблице SQL Server также используется в качестве ключа кластеризации, но это не обязательно должно быть так! Я лично видел значительное увеличение производительности, когда разбивал предыдущий основанный на GUID первичный / кластерный ключ на два отдельных ключа - первичный (логический) ключ в GUID и ключ кластеризации (упорядочения) в отдельном
INT IDENTITY(1,1)
столбце.Как Кимберли Трипп, королева индексации, и многие другие неоднократно заявляли,
GUID
что ключ кластеризации не является оптимальным, поскольку из-за его случайности он приводит к массовой фрагментации страниц и индексов и, как правило, к снижению производительности.Да, я знаю - есть
newsequentialid()
в SQL Server 2005 и более поздних версиях - но даже это не совсем и полностью последовательно и, следовательно, также страдает от тех же проблем, что иGUID
- чуть менее заметно.Затем следует рассмотреть еще одну проблему: ключ кластеризации в таблице будет добавлен к каждой записи в каждом некластеризованном индексе в вашей таблице - таким образом, вы действительно хотите убедиться, что он как можно меньше. Как правило, более
INT
2 миллиардов строк должно быть достаточно для подавляющего большинства таблиц - и по сравнению сGUID
ключом кластеризации вы можете сэкономить сотни мегабайт хранилища на диске и в памяти сервера.Быстрый расчет - использование
INT
против вGUID
качестве первичного ключа и ключа кластеризации:ИТОГО: 25 МБ против 106 МБ - и это только на одном столе!
Еще немного пищи для размышлений - отличный материал Кимберли Триппа - прочитайте его, прочитайте снова, переварите! Это на самом деле индексное Евангелие SQL Server.
PS: конечно, если вы имеете дело с несколькими сотнями или несколькими тысячами строк - большинство из этих аргументов не окажут большого влияния на вас. Однако: если вы попадаете в десятки или сотни тысяч строк или начинаете считать в миллионах - тогда эти точки становятся очень важными и очень важными для понимания.
Обновление: если вы хотите, чтобы ваш
PKGUID
столбец был вашим основным ключом (но не ключом кластеризации), а другой столбецMYINT
(INT IDENTITY
) - вашим ключом кластеризации - используйте это:По сути: вам просто нужно явно указать
PRIMARY KEY
ограничению, что оноNONCLUSTERED
(в противном случае оно создается как кластерный индекс по умолчанию), а затем вы создаете второй индекс, который определяется какCLUSTERED
Это будет работать - и это допустимый вариант, если у вас есть существующая система, которую необходимо «перепроектировать» для повышения производительности. Для новой системы, если вы начинаете с нуля и у вас нет сценария репликации, я бы всегда выбирал в
ID INT IDENTITY(1,1)
качестве своего кластерного первичного ключа - гораздо более эффективный, чем все остальное!источник
DATETIME
например, НЕ полезны для ключа кластеризации, поскольку они имеют точность только 3,33 мс, и, следовательно, могут существовать дубликаты. Таким образом , в таком случае, вы * еще нужноINT IDENTITY
вместо этого - следовательно, я обычно использую , что по умолчанию, так как frmo моих 20+ лет опыта, действительно использовать естественный ключ вряд ли когда - либо действительно существует ....Я использую GUID в качестве PK с 2005 года. В этом мире распределенных баз данных это абсолютно лучший способ объединения распределенных данных. Вы можете запустить и забыть таблицы слияния, не беспокоясь о совпадении целых чисел между объединенными таблицами. Соединения GUID могут быть скопированы без каких-либо забот.
Это мои настройки для использования GUID:
PK = GUID. Идентификаторы GUID индексируются аналогично строкам, поэтому для таблиц с высокими строками (более 50 миллионов записей) может потребоваться разбиение таблиц или другие методы повышения производительности. SQL Server становится чрезвычайно эффективным, поэтому проблемы с производительностью становятся все менее и менее применимыми.
PK Guid является некластеризованным индексом. Никогда не кластеризируйте индекс GUID, если это не NewSequentialID. Но даже тогда перезагрузка сервера приведет к серьезным перебоям в заказе.
Добавьте ClusterID Int к каждой таблице. Это ваш КЛАСТЕРНЫЙ индекс ... который заказывает ваш стол.
Объединение по ClusterID (int) более эффективно, но я работаю с 20-30 миллионами таблиц записей, поэтому объединение по GUID заметно не влияет на производительность. Если вы хотите максимальной производительности, используйте концепцию ClusterID в качестве основного ключа и присоединитесь к ClusterID.
Вот моя таблица электронной почты ...
источник
В настоящее время я разрабатываю веб-приложение с EF Core, и вот шаблон, который я использую:
Все мои классы (таблицы) и INT PK и FK. У меня есть дополнительный столбец с типом Guid (сгенерированный конструктором c #) с некластеризованным индексом.
Все соединения таблицы в EF управляются через клавиши int, а весь доступ извне (контроллеры) осуществляется с помощью направляющих.
Это решение позволяет не показывать клавиши int на URL-адресах, но позволяет поддерживать чистоту и порядок в модели.
источник
Если вы используете GUID в качестве первичного ключа и создаете кластерный индекс, тогда я предлагаю использовать для него значение по умолчанию NEWSEQUENTIALID ()
источник
Эта ссылка говорит, что это лучше, чем я мог, и помог в принятии решений. Я обычно выбираю int в качестве первичного ключа, если у меня нет особой необходимости, и я также позволяю SQL-серверу автоматически генерировать / поддерживать это поле, если у меня нет особых причин не делать этого. В действительности, проблемы производительности должны определяться на основе вашего конкретного приложения. Здесь есть много факторов, в том числе ожидаемый размер БД, правильная индексация, эффективные запросы и многое другое. Хотя люди могут не согласиться, я думаю, что во многих сценариях вы не заметите различий ни с одним из этих вариантов, и вам следует выбрать то, что больше подходит для вашего приложения, а что позволяет разрабатывать проще, быстрее и эффективнее (если вы никогда не завершите приложение какая разница для остальных :).
https://web.archive.org/web/20120812080710/http://databases.aspfaq.com/database/what-should-i-choose-for-my-primary-key.html
PS Я не уверен, почему вы бы использовали Composite PK или какую выгоду вы считаете, что это даст вам.
источник
В большинстве случаев его не следует использовать в качестве первичного ключа для таблицы, поскольку он действительно снижает производительность базы данных. полезные ссылки, касающиеся влияния GUID на производительность и в качестве первичного ключа.
источник
Наличие последовательных идентификаторов значительно облегчает хакеру или майнеру компрометации ваш сайт и данные. Имейте это в виду при выборе ПК для сайта.
источник