Ограничение производительности строк в качестве первичных ключей?
Каким будет ограничение производительности при использовании строк в качестве первичных ключей вместо bigint и т.д.? Сравнение строк намного дороже, чем целочисленное сравнение, но, с другой стороны, я могу себе представить, что внутренне СУБД будет вычислять хеш-ключи, чтобы уменьшить штраф.
Приложение, в котором я работаю, использует строки как первичные ключи в нескольких таблицах (MySQL). Это не тривиально изменить это, и я хотел бы знать, что может быть достигнуто с точки зрения производительности, чтобы оправдать работу.
Ответы
Ответ 1
с другой стороны, я могу представить, что внутренне СУБД будет вычислять хэш чтобы уменьшить штраф.
БД должно поддерживать B-Tree (или аналогичную структуру) с ключом, чтобы упорядочить их.
Если ключ хэширован и сохранил его в B-дереве, было бы неплохо быстро проверить уникальность ключа - ключ все еще можно эффективно искать. Но вы не сможете эффективно искать диапазон данных (например, с помощью LIKE
), поскольку B-Tree больше не упорядочивается в соответствии со значением String.
Итак, я думаю, что большинство БД действительно хранят String в B-Tree, которое может (1) принимать больше пространства, чем числовые значения, и (2) требовать, чтобы B-Tree был перебалансировать, если ключи вставляются в произвольном порядке (нет понятия увеличения значения как с числовым pk).
штраф на практике может варьироваться от незначительного до огромного. Все зависит от использования, количества строк, среднего размера строкового ключа, запросов, которые соединяют таблицу и т.д.
Ответ 2
В нашем продукте мы используем varchar (32) для первичных ключей (GUID), и мы не сталкивались с такими проблемами производительности. Наш продукт представляет собой веб-сайт с экстремальной перегрузкой и имеет решающее значение для стабильности.
Мы используем SQL Server 2005.
Изменить: В наших самых больших таблицах мы имеем более 3 000 000 записей с большим количеством вставок и выбираем их. Я думаю, в общем, преимущество перехода на ключ int будет очень низким, но проблемы при миграции очень высоки.
Ответ 3
Это зависит от нескольких факторов: RDBMS, количества индексов, связанных с этими столбцами, но в целом это будет более эффективно с использованием ints, представленным bigints.
Любое повышение производительности зависит от использования, поэтому без конкретных примеров схемы таблиц и рабочей нагрузки запроса это трудно сказать.
Если это не имеет смысла в домене (я думаю, что-то уникальное, например, номер социального страхования), суррогатный целочисленный ключ является хорошим выбором; ссылающиеся объекты не нуждаются в обновлении их справочника FK при изменении объекта ссылки.
Ответ 4
Одна вещь, на которую нужно обратить внимание - это разбиение на страницы (я знаю, что это может произойти в SQL Server - возможно, то же самое в MySQL).
Первичные ключи физически упорядочены. Используя целое число с автоматическим добавлением, вы гарантируете, что каждый раз, когда вы вставляете, вы вставляете следующий номер вверх, поэтому нет необходимости переустанавливать ключи для db. Однако, если вы используете строки, вы можете вставить pk в середине других ключей для поддержания порядка pk. Этот процесс переупорядочения pks на вставке может стать дорогим.