Как сохранить 128-битное число в одном столбце в MySQL? - PullRequest
35 голосов
/ 15 декабря 2010

Я изменяю некоторые таблицы для хранения IP-адресов в виде чисел, а не строк.Это просто с IPv4, где 32-битный адрес может помещаться в целочисленный столбец.Однако адрес IPv6 составляет 128 бит.

В документации MySQL показаны только числовые типы до 64 бит ("bigint").

Должен ли я придерживаться char /varchar для IPv6?(В идеале я хотел бы использовать один и тот же столбец для IPv4 и IPv6, поэтому я бы предпочел не делать этого).

Есть ли что-нибудь лучше, чем использование двух столбцов bigint?Я бы предпочел не разбивать значение на верхний и нижний / 64 при использовании адреса.

Я использую MariaDB 5.1 - если в более поздней версии MySQL есть лучшее решение, то это было бы неплохознать, хотя и не сразу:

[EDIT] Обратите внимание, что я рекомендую лучший способ сделать это - очевидно, что естьразличные способы сделать это (включая существующее строковое представление), но какой (с точки зрения производительности) лучше?(т. е. если бы кто-то уже сделал анализ, это спасло бы меня, или я упустил что-то очевидное, это было бы здорово знать тоже).

Ответы [ 3 ]

43 голосов
/ 02 сентября 2011

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

Я создал следующие таблицы, заполненные 2 000 000 случайных IP-адресов из 100 случайных сетей.

CREATE TABLE ipv6_address_binary (
    id SERIAL NOT NULL AUTO_INCREMENT PRIMARY KEY,
    addr BINARY(16) NOT NULL UNIQUE
);

CREATE TABLE ipv6_address_twobigints (
    id SERIAL NOT NULL AUTO_INCREMENT PRIMARY KEY,
    haddr BIGINT UNSIGNED NOT NULL,
    laddr BIGINT UNSIGNED NOT NULL,
    UNIQUE uidx (haddr, laddr)
);

CREATE TABLE ipv6_address_decimal (
    id SERIAL NOT NULL AUTO_INCREMENT PRIMARY KEY,
    addr DECIMAL(39,0) NOT NULL UNIQUE
);

Затем я выбираю все IP-адреса для каждой сети и записываю время отклика. Среднее время отклика в таблице с двумя значениями составляет около 1 секунды, а в двоичной таблице - около одной сотой секунды.

Вот вопросы.

Примечание:

X_ [HIGH / LOW] является наиболее / наименее значимым 64-разрядным из X

когда NETMASK_LOW равен 0, условие AND опускается, поскольку оно всегда возвращает true. не сильно влияет на производительность.

SELECT COUNT(*) FROM ipv6_address_twobigints
WHERE haddr & NETMASK_HIGH = NETWORK_HIGH
AND laddr & NETMASK_LOW = NETWORK_LOW

SELECT COUNT(*) FROM ipv6_address_binary
WHERE addr >= NETWORK
AND addr <= BROADCAST

SELECT COUNT(*) FROM ipv6_address_decimal
WHERE addr >= NETWORK
AND addr <= BROADCAST

Среднее время ответа:

График:

http://i.stack.imgur.com/5NJvQ.jpg

BINARY_InnoDB  0.0119529819489
BINARY_MyISAM  0.0139244818687
DECIMAL_InnoDB 0.017379629612
DECIMAL_MyISAM 0.0179929423332
BIGINT_InnoDB  0.782350552082
BIGINT_MyISAM  1.07809265852
4 голосов
/ 19 декабря 2010

Я всегда использовал либо строку, либо два 64-битных целых числа.Первый - в случае, когда я просто хочу записать его, второй - в случае, когда мне нужно выполнить расчеты относительно того, содержится ли определенный адрес в определенной сети, или даже если две сети перекрываются.

Когдасохраняя его как целое число, единственный вариант - разделить его на два 64-битных числа.Поскольку это делает сравнения более громоздкими, я бы не стал этого делать, если вам не нужны численные расчеты, чтобы посмотреть, попадает ли IP в определенную сеть.

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

И почему вы не сможете смешивать IPv4 и IPv6 встроковые поля?Их легко отличить при поиске.Их диапазон возможных значений не перекрывается.

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

1 голос
/ 15 декабря 2010

Цитата: "Вы рассматривали двоичный код (64)"

Хранение очень больших целых чисел в MySQL

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