Обычно существует два типа хеш-таблиц: откройтесь и закрытый.
В открытой хеш-таблице Вы находите правильный блок на основе хеша, и затем создаете список объектов, зависающих от того блока.
В закрытой хеш-таблице Вы находите начальный блок с помощью значения хэш-функции, и если это занято, Вы зондируете для следующего значения. В упрощенном случае можно сделать это путем поиска следующего свободного блока, или можно создать второе значение хэш-функции из объекта и ступить тем (хотя необходимо удостовериться, что это главное по модулю размер хэш-таблиц, таким образом, Вы посетите все блоки).
открытая хеш-таблица обычно не изменяется. Вы устанавливаете начальный размер, чтобы быть тем, что Вы чувствуете, разумно для проблемы. Поскольку другие указали, что Вы могли изменить размеры на открытой хеш-таблице, но обоснование о производительности этой структуры данных теперь становится очень трудным. Если Вы изменяете размеры, когда длина данного блока является L тогда, Вы могли бы заканчивать тем, что изменили размеры на просто L объекты в целой хеш-таблице, которая очень неэффективна.
А закрылся, хеш-таблица изменена когда коэффициент загрузки (нет. из объектов в хеш-таблице / нет. из блоков), поражает некоторое предопределенное значение. Я склонен использовать 80%, но точное значение вряд ли будет слишком очень важно.
преимущество закрытой хеш-таблицы - то, что амортизировал , стоимость вставки объекта всегда O (1) (принятие хорошей хеш-функции). Вставка конкретного объекта могла бы быть O (N) из-за стоимости изменения размеров, но это делается очень нечасто.
Я бы посоветовал посмотреть, какие типы запросов вы будете выполнять, чтобы решить, какой формат вы выберете.
Только если вам нужно вытащить или сравните отдельные октеты, если бы вам пришлось рассмотреть возможность их разделения на отдельные поля.
В противном случае сохраните его как 4-байтовое целое число. Это также дает возможность использовать встроенные в MySQL функции INET_ATON ()
и INET_NTOA ()
.
Хранилище:
] Если вы собираетесь поддерживать только адреса IPv4, тогда вашим типом данных в MySQL может быть UNSIGNED INT
, который использует только 4 байта памяти.
Для хранения отдельных октетов вам нужно будет использовать только ] UNSIGNED TINYINT
типов данных, а не SMALLINTS
, которые будут использовать по 1 байту каждого хранилища.
Оба метода будут использовать одинаковое хранилище, возможно, немного больше для отдельных полей для некоторых накладных расходов.
Дополнительная информация:
Производительность:
Использование одного поля даст гораздо лучшую производительность, это одно сравнение вместо 4. Вы упомянули, что вы будете выполнять запросы только для всего IP-адреса, поэтому необходимости в этом не должно быть. держите октеты отдельно. Использование функций MySQL INET _ *
выполнит преобразование между текстовым и целочисленным представлениями один раз для сравнения.
Производительность:
Использование одного поля даст гораздо лучшую производительность, это одно сравнение вместо 4. Вы упомянули, что вы будете выполнять запросы только для всего IP-адреса, поэтому необходимости в этом не должно быть. держите октеты отдельно. Использование функций MySQL INET _ *
выполнит преобразование между текстовым и целочисленным представлениями один раз для сравнения.
Производительность:
Использование одного поля даст гораздо лучшую производительность, это одно сравнение вместо 4. Вы упомянули, что вы будете выполнять запросы только для всего IP-адреса, поэтому необходимости в этом не должно быть. держите октеты отдельно. Использование функций MySQL INET _ *
выполнит преобразование между текстовым и целочисленным представлениями один раз для сравнения.
Мне кажется, что отдельные поля не имеют особого смысла - во многом как разделение почтового индекса на разделы или телефонный номер.
Может быть полезно, если вам нужна конкретная информация по разделам, но Я не вижу реальной причины не использовать 32-битное int.
A BIGINT
- это 8
байтов в MySQL
.
Для хранения IPv4
адресов, UNSINGED INT
достаточно, и я думаю, это то, что вы должны использовать.
Я не могу представить сценарий, в котором 4
октета будут иметь большую производительность, чем один INT
, и последнее намного удобнее.
Также обратите внимание, что если вы собираетесь выдавать такие запросы:
SELECT *
FROM ips
WHERE ? BETWEEN start_ip AND end_ip
, где start_ip
и end_ip
- столбцы в вашей таблице, производительность будет низкой.
Эти запросы используются, чтобы узнать, находится ли данный IP
в пределах диапазона подсети (обычно для его запрета).
Чтобы сделать эти запросы эффективный, вы должны сохранить весь диапазон как объект LineString
с индексом SPATIAL
на нем,и запросите примерно так:
SELECT *
FROM ips
WHERE MBRContains(?, ip_range)
См. эту запись в моем блоге для получения более подробной информации о том, как это сделать:
Используйте PostgreSQL, для этого есть собственный тип данных .
Более серьезно, я бы попадают в лагерь "одного 32-битного целого". IP-адрес имеет смысл только тогда, когда все четыре октета рассматриваются вместе, поэтому нет причин хранить октеты в отдельных столбцах в базе данных. Вы бы сохранили номер телефона, используя три (или более) разных поля?
Эффективное преобразование ip в int и int в ip (может быть вам полезно): (PERL)
sub ip2dec {
my @octs = split /\./,shift;
return ($octs[0] << 24) + ($octs[1] << 16) + ($octs[2] << 8) + $octs[3];
}
sub dec2ip {
my $number = shift;
my $first_oct = $number >> 24;
my $reverse_1_ = $number - ($first_oct << 24);
my $secon_oct = $reverse_1_ >> 16;
my $reverse_2_ = $reverse_1_ - ($secon_oct << 16);
my $third_oct = $reverse_2_ >> 8;
my $fourt_oct = $reverse_2_ - ($third_oct << 8);
return "$first_oct.$secon_oct.$third_oct.$fourt_oct";
}