1

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

Возьмем, например, следующий псевдокод:

// set code, date released, collector number, name 
$crc = crc32(implode(',', ['A', '1993-08-03', '232a', 'black lotus'])); 
echo $crc; // 4199975187 

Возможное количество карт парит только около 25k сейчас и растет около 100-300 каждые 6 месяцев.

  1. У этого курса не будет столкновения справа?
  2. Это хорошая практика? Есть ли у меня другие хорошие альтернативы?

Я знаю, что может сделать хэш короче, преобразовав его в base 62, но я буду присоединяться к этим запасам столу пользователей, так что я думаю, поддерживая их в int будет лучшим вариантом.

+0

В целом, «интеллектуальный ключ» (такой как ключ, созданный из конкатенированных столбцов), является идеей _bad_. Не могли бы вы объяснить, почему «суррогатный ключ» не решает вашу проблему? Ключ - это просто уникальный номер, как это важно, если значение ключа также соответствует порядку вставки? – hashbrown

+0

Этот идентификатор будет отображаться для пользователей, просматривающих приложение. Скорее всего, в параметре $ _GET. Я не хотел, чтобы они догадывались о том, какие карты были вставлены в базу данных на основе идентификаторов, которые у них были. – voldomazta

+0

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

ответ

2

Я возражаю к этому:

Это проблематично с суррогатным ключом, потому что они добавляются в базу данных с последним автоматическим приращением, и я не хочу их идентификаторы в зависимости от того, что они были вставлено.

ID (правильно: «Идентификатор», так как это аббревиатура, а не аббревиатура) является аббревиатурой «идентичность», который имеет единственное свойство быть уникальным для каждого элемента, то есть, он используется для идентификации каждый элемент. Вы не должны придавать этому никакого другого значения, поэтому монотонно увеличивается его количество с помощью порядка вставки, и сортировка данных с помощью сгенерированного столбца идентификации бессмысленна (если только он не используется внутри индекса, используемого для поиска по-Id). В этом случае вы должны рассматривать идентификаторы как непрозрачные.

Конечно, если вы используете дайджест (например, CRC-32), порядок сортировки идентификаторов бессмыслен, но на самом деле представляет меньшую полезность, чем монотонно возрастающий Id.

Вы правильно определили риск столкновения хэшей, пространство пробелов CRC-32 составляет всего 32 бита, и если у вас есть 25 000 карт, то проблема дня рождения говорит нам о шансах хэш-столкновений в таком небольшом диапазоне пространство не является незначительным.

Просто используйте значение, генерируемое автогенератором. :)

Использование расчетного хэша в качестве идентификатора/ключа имеет полезность - это то, как работают хеш-таблицы, благодаря чему вы можете быстро найти что-то по значению, не просматривая всю таблицу (например, чтобы найти карту Black Lotus, возьмите хэш своих свойств так же, как и вы, а затем просмотрите вычисленный хеш в столбце идентификатора, без необходимости делать SELECT ... WHERE code = 'A' AND ... AND name = 'black lotus', но сначала требуется знать каждое значение свойства, и если вы настроите правильную табличные индексы быстро становятся спорными.

Основная проблема с использованием хэш в качестве первичного ключа является то, что:

  1. Первичные ключи должны быть неизменны («никогда не меняется»)
  2. Ключ теперь зависит от данных
  3. Если изменения данных (например, «blcak lotus» становится «Black Lotus»), тогда ключ является недопустимым и должен быть воссоздан, но вы не можете этого сделать, потому что ключи неизменяемы ... рендеринг ранее вычисленного идентификатора недействителен.

QED :)

+0

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

+0

@Tim. Эффективность прибыли сегодня невелика - стоимость индексации столбца с 4-байтовым целочисленным значением примерно такая же, как 4-байтовое значение символа, например, даже значение «nvarchar (255)» может быть просмотрено - в индексе очень быстро. Даже если вы microbenchmarked это (само нереалистичный сценарий, учитывая все остальное, что происходит в большинстве приложений баз данных), я сомневаюсь, что вы увидите какую-либо разницу вообще для строк менее 20 символов или около того. – Dai

+0

Это так неправильно на уровне предприятия. Важность упорядоченных, одинаково распределенных ключей - это разница в ночных и дневных для производительности БД при значительном числе строк и значительном потоке запросов. Если у вас несколько сотен строк и несколько запросов в секунду, любой ключ будет делать. Масштабируйте это миллионы строк с тысячами запросов в секунду, и ваша БД будет таять с плохо разработанным ключом. – Tim

-1

Исследование это ссылка: - http://preshing.com/20110504/hash-collision-probabilities/

Вы увидите, что для любого 32 бит хэша и 25K плюс оценивает шансы столкновения почти 1 в 10 - независимо от того, насколько хорош алгоритм хеширования.

Вам либо нужен механизм для борьбы с столкновениями, либо переход на 64-битный алгоритм хеширования. CRC64, казалось бы, был бы достаточно хорош в соответствии с этим crc collisions at various bit sizes 18,2 миллиона образцов с нулевыми столкновениями.

+0

Хотя ваши хэш-комментарии отмечены точками, использование хэша значений дней для первичного ключа является * очень плохой идеей. – Tim

+0

@Tim - на лице этого вы правы. Но я подозреваю, что ОП может иметь вескую причину для хеша (не явный из его вопроса), и в любом случае я хочу убедиться, что любой случайный читатель этой темы не уйдет с впечатлением, что CRC32 - хороший способ получить уникальные ключи. –

Смежные вопросы