Лучшая хеш-функция для смешанных числовых и литеральных идентификаторов - PullRequest
6 голосов
/ 14 декабря 2009

По соображениям производительности мне нужно разбить набор объектов, идентифицированных строкой, на группы. Объекты могут быть идентифицированы либо числом, либо строкой в ​​префиксной (квалифицированной) форме с точками, разделяющими части идентификатора:

12
323
12343
2345233
123123131
ns1:my.label.one
ns1:my.label.two
ns1:my.label.three
ns1:system.text.one
ns2:edit.box.grey
ns2:edit.box.black
ns2:edit.box.mixed

Числовые идентификаторы от 1 до нескольких миллионов. У текстовых идентификаторов, скорее всего, очень много, начиная с одного префикса пространства имен (ns1 :) и с одинаковым префиксом пути (edit.box.).

Какова лучшая хеш-функция для этой цели? Было бы хорошо, если бы я мог как-то предсказать размер сегмента на основе статистики идентификатора объекта. Есть ли хорошие статьи для построения хорошей хэш-функции на основе статистической информации?

Существует несколько миллионов таких идентификаторов, но цель состоит в том, чтобы разбить их на группы по 1-2 тысячи на основе хеш-функции.

Ответы [ 3 ]

3 голосов
/ 14 декабря 2009

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

Итак, ваша хеш-функция может выглядеть так:

if it's an integer value:
    return int_hash(integer value)
return string_hash(string value)

Если нет каких-либо скоплений ваших целых чисел вокруг определенных значений по модулю N, где N - возможное количество сегментов, то int_hash может просто вернуть свой ввод.

Выбор хеш-строки не является новой проблемой. Попробуйте "djb2" (http://www.cse.yorku.ca/~oz/hash.html) или аналогичный, если у вас нет непристойных требований к производительности.

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

Если вы сделаете это, и хеш не будет работать неожиданно плохо, и вы поместите свои несколько миллионов значений хеш-функции в несколько тысяч сегментов, тогда совокупности блоков будут нормально распределены со средним значением (несколько миллионов / несколько тысяч). ) и дисперсия 1/12 (несколько тысяч) ^ 2

При среднем значении 1500 записей на группу это стандартное отклонение составляет примерно 430. 95% нормального распределения находится в пределах 2 стандартных отклонений от среднего, поэтому 95% ваших групп будут содержать 640-2360 записей, если только Я сделал мои суммы неправильно. Это достаточно, или вам нужны ведра более близких размеров?

0 голосов
/ 14 декабря 2009

Я считаю, что CRC16 был бы разумным хэшем для этих строк, и группы не должны превышать 1-2 тысячи.

Это должно сделать хеш-таблицу около 1 МБ + сколько бы элементов у вас в ней не было * 4 байта, поэтому мы говорим о 50 МБ, а затем у вас также есть все фактические данные, которые должны быть сохранены, которые лучше было бы очень маленькими.

0 голосов
/ 14 декабря 2009

Вы, вероятно, будете в безопасности, выбрав sha1 и обрезав его до нужного размера.

Это не будет чрезвычайно эффективно, но, возможно, хеш-функция не станет узким местом?

...