Как найти определенный IP-адрес в быстром режиме в заданном диапазоне IP-адресов или подсетях?

Как оптимизировать процесс обработки и добавления большого объема IP-адресов из исходного файла в формате CSV в базу данных для ускорения процесса и улучшения эффективности, учитывая расчетное время для формирования выходных данных и добавления их в базу?
  • 22 февраля 2024 г. 14:28
Ответы на вопрос 4
Для быстрого поиска определенного IP-адреса в заданном диапазоне или подсети можно воспользоваться утилитами или программами для работы с IP-адресами, например, ipcalc или ipcalc-ng. Эти инструменты позволяют выполнять операции над IP-адресами, включая поиск адресов в заданных диапазонах.

Чтобы оптимизировать процесс обработки и добавления большого объема IP-адресов из CSV файла в базу данных, можно использовать следующие подходы:

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

2. Проиндексируйте столбец с IP-адресами в вашей таблице базы данных. Индексирование ускоряет процесс поиска и добавления данных.

3. Оптимизируйте запросы к базе данных, используя подходящие индексы, правильные типы данных и оптимизированные запросы SQL.

4. Разделите обработку данных на параллельные потоки или процессы для улучшения эффективности. Это может ускорить процесс добавления большого объема IP-адресов.

5. Периодически проверяйте и оптимизируйте процесс обработки и добавления IP-адресов, чтобы улучшить его производительность.

Соблюдая эти рекомендации, можно существенно ускорить процесс обработки и добавления большого объема IP-адресов из CSV файла в базу данных.
В PostgreSQL есть специальный тип данных для хранения адресов и набор функций для работы с ними
Если стоит задача именно максимально быстрого поиска, то вот тут я уже отвечал на похожий вопрос: Как ускорить поиск элементов из статичного string[] по подстроке? и там же есть ссылка на готовый код примера реализации на шарпе. Если кратко: тупо дерево таблиц переходов, на весь диапазон IPv4 - 17 гигабайт памяти и практически мгновенный поиск. Если на списках - то поиск примерно в 1-1000 раз медленнее и значительнее меньше затраты памяти. 
Примерно так:
public struct Organization
{
    public UInt64 Asn;
    public string Name;
}

var tree = ArrayTree<Organization>();
var org1 = new Organization() { Asn = 13238, Name = "YANDEX LLC" };
tree.Add(IPAddress.Parse("5.45.192.0").GetAddressBytes(), org1);


В данном случае немного доработать логику путем добавления в узел еще одного поля с cылкой на структуру организации и в диапазонах втором/третьем байте сначала проверять это поле, а потом уже дальше по цепочке идти. Ну или можно для простоты сгененрировать конечные узлы для каждой организации и просто сразу на втором/третьем шаге их линковать для нужного числа адресов, что позволит сократить расход памяти.

Измерил расход памяти для 400к записей: 1.6 и 3.6GB для х86 и х64 соответственно для ArrayTree. Для ListTree - 400 Мб.
Вообще, лучшая структура данных для этого - trie. Диапазоны, я уверен, идут так, что там фиксированно сколько-то начальных бит, а все оставшиеся - любые - все попадают в эту подсеть. Более того, все эти коды префиксные - ни один не будет началом другого. 

Поэтому вам надо лишь эти префиксы в trie сложить, а в вершине сохранить саму запись. При запросе надо спускаться по битам айпишника в trie, пока не упретесь в лист - вот он и соответсвтует искомому диапазону.

Если хотите использовать существующие БД, то можно сохранить в любой реляционной базе данных начала диапазонов. По запросу IP вам надо найти последнюю стороку не больше его. Буквально
where range_start <= IP order by range_start desc limit 1
.

Смотрите только аккуратно, что сравнивать их надо как битовые строки/32-битные числа, а не просто как строки. Ибо должно выполнятся 127.0.01 > 8.8.8.8. Сравнение как строки же не сработает. Или храните как битовые строки, или преобразуйте в числа, или нулями отбивайте октеты, короче трех символов.

Раскрывать все 4 миллиарда айпишников в отдельные записи - вообще не работающая идея.
Похожие вопросы