Как стать автором
Обновить

Комментарии 10

Давно (лет 5 назад) я делал примерно то же самое (определение страны по IP) через Redis (sorted sets) и операцию ZRANGEBYSCORE. Сложность операции O(log(N)). В Redis загоняются только диапазоны адресов (начало-конец).


Гуглится по "zrangebyscore ip lookup" и поиск возвращает довольно много результатов, включая и сравнения с SQL.

Интересный способ, спасибо
В нашем случае это была бы + лишняя зависимость, а БД и nginx по дефолту есть почти в любом сервисе
Почему бы не взять все существующие в мире автономные системы AS, разбитые про странам, в каждой автономной системе есть несколько подсетей различной размерности, далее мы начало и конец каждой подсети конвертируем в числовое значение и сравниваем нужный IP адрес (предварительно сконвертированный в число) на предмет вхождения в определенную подсеть…
Стоит отметить, что измерения производились в клиенте PostgreSQL — и свели к минимуму оверхед языка программирования.

В чём смысл такого измерения? Реально это будет запрос по сетке — и тут нас уже начнёт тормозить сетка — и микросекунды превращаются в миллисекунды, практически нивелируя все оптимизации.


Если вам действительно нужно быстродействие и вы боретесь за доли секунды… с учётом того что IPv4 сеток не так уж много (~850K) это всё легко держится в памяти в Trie-подобной структуре и ищется практически мгновенно без всяких оверхедов с БД и её индексами. С IPv6 ещё проще, сеток ~123K всего.

Эти измерения могут быть полезны если, например, БД работает как сервис (логика в БД + хайлоад). Будет важно быстро определять подзапросом страну.

За вариант с хранением в памяти спасибо
Благодарю, что поделились опытом.
ip4r не использовал, но нужен был максимально быстрый редирект пользователя, исходя из его локации.
Раньше хранил IP в виде числовых рэнжей (int8range) + Gist индекс. Скорость была ~3000 мкс с оверхедами ORM, учитывая время на конвертацию IP пользователя в decimal (~30 мкс).
Сейчас загружаю базу ip2location из файлов в память на старте, ~3гб RAM занимает.
Диапазоны хранятся числовыми значениями. IP ищу обычным бинарным поиском O(log n).
Итого, средняя скорость со всеми оверхедами стала ~100 мкс.

В базе MaxMind очень много неточностей когда надо определять регион/город. Сойдет только для страны. Ещё там нет часовых поясов.
Использую бесплатную базу ip2location (db11), она намного больше по объему, но сильно точнее.
~3 млн записей ipv4 и ~4 млн ipv6.
Время поиска ~100 мкс выходит именно по этой базе.

есть же timescaledb
ну и clickhouse никто не отменял

Можете пояснить свой комментарий?

Не раз наша команда в Каруне сталкивались с задачей, связанной с хранением и использованием IP-адресов в базе данных. Предположим, что есть типичная задача: необходимо парсить огромное количество диапазонов адресов (~300k) с известного ресурса, а далее определять страну по IP-адресу клиента. Кажется, ничего особенного. Это довольно просто решается любым ниже описанным способом при малых нагрузках. Но если у нас тысячи пользователей, или наш сервис является прокси перед всеми остальными? В этом случае не хочется быть бутылочным горлышком и приходится бороться за каждую долю секунды.

Поиск по clickhouse занимает оч мало времени. TimescaleDB в этом плане тоже покажет себя лучше чем postgresql. Понятно, что на Postgresql завязана бизнес логика, но clickhouse позволяет совмещать полезности.
Более подробно можете послушать Алексея Миловидова https://devzen.ru/episode-0334/

Вы меня простите, конечно, но вы статью читали вообще? Речь о том, что нужно выполнить поиск по диапазонам адресов (фактически чисел). Какой выигрыш от TimescaleDB (которая, фактически, расширение для PostgreSQL) тут может быть? И насколько?
Или еще и здоровую ClickHouse для этого ставить и обслуживать?
300к диапазонов спокойно влезут в память и я, например, предложил просто Redis. Я понимаю если бы вы, например, Tarantool предложили.

Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.