Pull to refresh

Comments 9

Версию от MaxMind не рассматривали в качестве альтернативы?
В MaxMind разве можно добавить свои данные?
Нельзя.
А зачем вам добавлять свои данные? Поделитесь сценарием.
Например, мне нужна не гео-база, а база ip ботов. Или провайдеров. Или вообще, всё вместе. Тогда я собираю одну базу:
  • гео — на основе того же maxmind
  • боты — на основе, к примеру ipgrabber
  • провайдеры — отдельным скриптом собираю инфу в RIPE

И всё. С помощью этой тулзы я смогу одним запросом получить всю необходимую инфу, а не держать 3 разные библиотеки, не инициализировать их все и не делать к к каждой по запросу.

Ведь IP база — это не только геолокация…
ограничение по количеству справочников;

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

Это уже больше возможность API. В принципе сам формат позволяет это сделать. Но из-за оптимизаций при сохранении файла, это немного лишается смысла. Оптимизации заключаются в склеивании идущих подряд записей, которые ссылаются на один элемент справочника (т.е. если, к примеру, идет 10 IP диапазонов в Москве, то они сохраняются в базу как один, но вывести границы этого большого диапазона не проблема).

Что касается вашей реализации.
Бегло глянул, вы по сути выкинули главное :)
Убрали основной индекс, и оставили индекс первых байт IP. А также выкинули бинарный поиск, и сделали обычный перебор.

В моём случае, основное предназначение индекса первых байт было убрать кучу повторяющихся первых байт из базы, тем самым заметно снизив размер базы, и ускорив поиск, так как нужно было сравнивать на один байт меньше (тем более этот байт почти всегда в блоке был одинаковый).

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

Но более того у вас похоже ошибка в алгоритме, так как даже индекс по первым байтам не очень хорошо работает.

Сгенерил по вашим примерам базу на основе Geolite City. И ради интереса запустил тест скорости (получилось меньше 200 запросов в секунду, что озадачило, учитывая что в SxGeo обычно скорость без кеширований около 18 тысяч).
Посмотрел исходник и смутилj вычисление $start и $stop для выборки нужного блока.

Добавил
echo "$start - $stop\n"; 

перед
$blockCount = $stop-$start;

и увидел, что при любом ip у вас $stop равен последнему блоку. Т.е. всегда выборка до конца. В итоге получается для IP начинающихся на 1 в переменную $blocks запихивает все блоки, а это в данном случае 15 МБ.

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

Извиняюсь, многословно получилось :)
и увидел, что при любом ip у вас $stop равен последнему блоку. Т.е. всегда выборка до конца.

Ого! Вот это я накосячил! Спасибо!
Также не совсем понял, у вас нет зависимостей между справочниками? Ну чтобы когда находишь город, в этой записи были ссылки на соответствующие записи в справочниках региона и страны.

У меня нет возможности указать зависимости между справочниками.
В моём примере информация о городе, регионе и стране хранится в одном справочнике «geo». При желании, можно сделать три справочника (город, регион, страна), что уменьшит размер базы, но увеличит количество дисковых операций при поиске. Но опять же, связь будет только между диапазоном и справочником.
что уменьшит размер базы

С базами городов, очень большой оверхед получается, если хранить, как в вашем случае записи фиксированной длины (тоже по началу был соблазн так сделать, чтобы ускорить выборку). Но есть там всякие городки с «километровыми» названиями, у такого городка может быть один крошечный диапазон IP, но из-за него разбухает вся база. А если туда еще как в случае с SxGeo записать подробную инфу о регионе и стране (включая названия на 7 языках). То размер справочников будет в несколько раз больше, чем сами диапазоны.

К примеру у меня в SxGeo Max Multi названия стран на 7 языках занимают в виде текста до 380 байт, если их записывать в каждый город (их 84 000) получится оверхед 32 МБ, в базе SxGeo справочник стран занимает 30 КБ, а вся база полностью 17,8 МБ. По моему не лучшее решение, чтобы вместо дополнительной мелкой операции чтения плодить лишние 32 МБ. Регионы до 490 байт, города до 230.

Это получается 380+490+230 (города) умножаем на количество записей городов 84000 получается 92 МБ + еще 15 МБ сами диапазоны итого 107 против 17,8, как по мне многовато за 2 дополнительных операции чтения по 500 байт. У Maxmind вообще прыжки по файлу на каждый бит IP-адреса и ничего :)
В моём случае случае, задача по проектированию справочников ложится на пользователя инструмента. В документации я привёл всего лишь пример (хотя признаю, крайне неудачный. Обещаю поправить).
Что касается связи между справочниками — я пока не придумал, как это реализовать в универсальном механизме. У Вас это решается кодом, но у вас более узкая задача.
Исправил работу индекса, провёл сравнительный тест, результаты уже поинтереснее :)
Sign up to leave a comment.

Articles