Повышение производительности запроса ip-геолокации

Предположим, есть таблица location_block, которая транслирует адреса ipv4 в геолокацию:

columns: ipmin <INT UNSIGNED> | ipmax <INT UNSIGNED> | id_location <MEDIUMINT UNSIGNED>
indexes: ipmin <UNIQUE> | ipmax <UNIQUE>
size: 2Mi rows
storage engine: InnoDB
ps: no overlapping among ip ranges

Вы можете определить геолокацию адреса ipv4, выполнив следующий запрос BETWEEN:

SELECT `id_location`
FROM `location_block`
WHERE '1234567890' BETWEEN `ipmin` AND `ipmax`
LIMIT 1

Однако это довольно медленно (~ 1 сек).

Предложение по улучшению
Согласно @RickJames (блоки адресов) можно оптимизировать этот BETWEEN запрос, просматривая только половину таблицы. Также предоставляется код (Эталонная реализация для IPv4).

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

Вопрос
Можно ли сделать более простой код? Предпочтительнее «читабельный запрос» или отдельная процедура? Как? Будет ли это быстрее, чем запрос BETWEEN?

Следовать за

Для записей, наконец, я разработал процедуру ниже, которая работает намного быстрее (~ 1 мс):

main:BEGIN
    
    DECLARE _ipmax INT unsigned;
    DECLARE _idloc MEDIUMINT unsigned;

    SELECT `ipmax`, `id_location`
    INTO _ipmax, _idloc
    FROM `location_block`
    WHERE `ipmin` <= _ip
    ORDER BY `ipmin`  DESC
    LIMIT 1;

    IF( (_idloc IS NULL) OR (_ip > _ipmax) ) THEN
        LEAVE main;
    END IF;

END

person Mark Messa    schedule 29.11.2017    source источник
comment
Взгляните на блоки адресов, такие как IP-адреса. Он использует непересекающиеся диапазоны для оптимизации поиска.   -  person Solarflare    schedule 30.11.2017
comment
Блог содержит пример кода (в разделе Эталонная реализация IPv4). Вы можете захотеть поэкспериментировать с ним, и если что-то не работает, вы должны задать конкретные вопросы (иначе, все, что мы можем сделать, это повторить то, что уже написано в блоге. Реализация должна решить именно вашу проблему). Кроме того, Рик является участником stackoverflow, поэтому он может взглянуть на вашу проблему, если вы где-то застряли с его кодом.   -  person Solarflare    schedule 30.11.2017


Ответы (1)


Вы оставили размер буфера по умолчанию? Если это так, попробуйте отредактировать файл my.cnf и установить innodb_buffer_pool_size=1G

person Larry OBrien    schedule 29.11.2017