Выбор типа первичного ключа - PullRequest
0 голосов
/ 27 августа 2009

У меня есть таблица, которая потенциально может иметь большое количество вставок в секунду, и я пытаюсь выбрать тип первичного ключа, который я хочу использовать. Для иллюстрации скажем, это таблица пользователей. Я пытаюсь выбрать между использованием GUID и BIGINT в качестве первичного ключа и, в конечном счете, в качестве UserID во всем приложении. Если я использую GUID, я сохраняю поездку в базу данных для генерации нового идентификатора, но GUID не «удобен для пользователя», и невозможно разделить таблицу по этому идентификатору (что я планирую сделать). Использование BIGINT намного удобнее, но генерировать его - проблема. Я не могу использовать IDENTITY (для этого есть причина), поэтому мой единственный выбор - иметь некоторую вспомогательную таблицу, которая будет содержать последний использованный идентификатор, и затем я вызываю это сохраненный процесс:

create proc GetNewID @ID BIGINT OUTPUT
as
begin
update HelperIDTable set @ID=id, id = id + 1 
end

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

Мне действительно нравится идея использовать BIGINT в качестве pk, но проблема узкого места касается меня - есть ли способ грубо оценить, сколько идентификаторов он может произвести в секунду? Я понимаю, что это сильно зависит от аппаратного обеспечения, но есть ли какие-то физические ограничения и на какую степень мы смотрим? 100 'S / сек? 1000-х / сек

Любые идеи о том, как подойти к проблеме, высоко ценятся! Эта проблема не дает мне спать много ночей!

Спасибо! Андрей

Ответы [ 5 ]

2 голосов
/ 27 августа 2009

GUID кажется естественным выбором - и, если вам действительно нужно, вы, вероятно, можете поспорить, чтобы использовать его для PRIMARY KEY таблицы - единственное значение, которое однозначно идентифицирует строку в базе данных.

Что я настоятельно рекомендую не делать, так это использовать столбец GUID в качестве ключа кластеризации, что SQL Server делает по умолчанию, если вы специально не запретите это.

Как Кимберли Трипп - Королева индексирования - и другие неоднократно заявляли - GUID, так как ключ кластеризации не является оптимальным, поскольку из-за его случайности он приведет к массивной странице и фрагментация индекса и вообще плохая производительность.

Да, я знаю - в SQL Server 2005 и более поздних версиях newsequentialid() - но даже это не совсем и полностью последовательно и, следовательно, также страдает от тех же проблем, что и GUID - только чуть менее заметно.

Затем следует рассмотреть еще одну проблему: ключ кластеризации в таблице будет добавлен к каждой записи в каждом и каждом некластеризованном индексе в вашей таблице - таким образом, вы действительно хотите убедиться, что он настолько мал, насколько это возможно. , Как правило, INT с 2+ миллиардами строк должно быть достаточно для подавляющего большинства таблиц - и по сравнению с GUID в качестве ключа кластеризации вы можете сэкономить сотни мегабайт хранилища на диске и в памяти сервера.

Итак, подведем итог: если у вас нет веских причин, я бы всегда рекомендовал поле INT IDENTITY в качестве первичного / кластеризованного ключа в вашей таблице.

Марк

1 голос
/ 27 августа 2009

Хотите ли вы первичный ключ по деловым причинам или защищенный ключ для хранения? См. stackoverflow.com / questions / 1151625 / int-vs-unique-identifier-for-id-field-in-database для более подробного сообщения на тему PK против кластерного ключа.

Вы действительно должны понять, почему вы не можете использовать IDENTITY. Генерация идентификаторов вручную, и особенно на сервере с дополнительным rountrip и обновлением только для генерации каждого идентификатора для вставки, которая не будет масштабироваться. Тебе повезет достичь более 100 секунд в секунду. Проблема заключается не только в продолжительности цикла и времени обновления, но в основном в результате взаимодействия обновления генерации идентификатора с пакетной вставкой: транзакция пакетной вставки будет сериализовать генерацию идентификатора. В основе работы лежит разделение генерации идентификаторов в отдельном сеансе, чтобы он мог выполнять автоматическую фиксацию, но тогда пакетная вставка не имеет смысла, потому что генерация идентификатора не пакетирована: у нее есть для ожидания сброса журнала после каждого идентификатора, сгенерированного в порядке совершать. По сравнению с этим uuid будут бегать круги вокруг вашей ручной генерации идентификатора. Но из-за фрагментации uuid - ужасный выбор для зарезервированного ключа.

1 голос
/ 27 августа 2009

Я пытаюсь использовать GUID PK для всех таблиц, кроме небольших таблиц поиска. Концепция GUID обеспечивает безопасное создание идентификатора объекта в памяти без обращения к базе данных и последующего сохранения без изменения идентификатора.

Когда вам нужен «читабельный» идентификатор, вы можете использовать автоинкремент int при сохранении. Для разделения можно также создать BIGINT позже по расписанию базы данных для многих пользователей за один раз.

0 голосов
/ 27 августа 2009

Идея, которая требует серьезного тестирования: попробуйте создавать (вставлять) новые строки партиями, скажем, 1000 (10 000 × 1M?) За раз. Вы можете иметь основную (aka bottleneck) таблицу со списком следующей для использования, или у вас может быть запрос, который делает что-то вроде

 select min(id) where (name = '')

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

Параметр разбиения таблицы: в предположении столбца идентификатора bigint, как вы определяете раздел? Если вы допускаете количество строк в 1G в день, вы можете настроить новый раздел вечером (день1 = 1 000 000 000 - 1 999 999 999, день 2 = 2 000 000 000 - 2 999 999 999 и т. Д.) И затем заменить его, когда он будет готов. Конечно, вы ограничены 1000 разделами, поэтому с bigints у вас закончатся разделы до того, как у вас закончатся идентификаторы.

0 голосов
/ 27 августа 2009

попробуйте поразить вашу базу данных скриптом, возможно, с использованием jmeter для имитации одновременных попаданий Возможно, вы можете просто измерить себя, сколько нагрузки вы можете выдержать. Также ваша БД может вызвать бутылочное горлышко. Который из них? Я бы предпочел PostgreSQL для большой нагрузки, как Yahoo и Skype также делают

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...