[Moscow.pm] Написал интерфейс к базе от ipgeobase.ru

Sergey Zhuravlev sergey.zhuravlev на gmail.com
Пн Ноя 30 23:50:52 PST 2009


2009/12/1 Ruslan Zakirov <ruslan.zakirov на gmail.com>:
> Странные цифры. Больше похоже на баг mysql. Можете прислать EXPLAINы
> для обоих запросов?

mysql> explain select * from ipgeobase where istart <= 62432 and iend
>= 62432 order by iend-istart asc limit 1 \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: ipgeobase
         type: range
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: NULL
         rows: 26824
        Extra: Using where; Using filesort
1 row in set (0.00 sec)

mysql> explain select * from ipgeobase where istart <= 62432 order by
istart desc limit 1 \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: ipgeobase
         type: range
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: NULL
         rows: 26824
-- limit не учитывается в explain, поэтому тот неправильное число,
-- реально - один лукап по индексу и выборка одной строки.
        Extra: Using where
1 row in set (0.00 sec)

> Вот вы подумайте. Да, это range scan, но он ограничен с двух сторон.
> Индекс отсортирован по возрастанию по обоим колонкам. По этому mysql
> находит точку по istart и начинает сканирование вверх (к уменьшению) и
> должна остановиться как только iend станет меньше нужного нам
> значения. В итоге должно быть просмотрено записей максимум на две
> больше чем реально будет возвращено.

Недавно прочитал замечательную аналогую двухколоночного индекса.
Есть адресная книга, контакты отсортированы сначала по фамилии, а
потом по имени.
Нам нужно выбрать тех, у кого фамилия меньше чем "Иванов" и имя больше
чем "Сергей".
Очевидно, что придётся просматривать последовательно всех, кто
соответствует первому условию.

> Можете сравнить запросы совсем без сортировок?

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

без сортировки - долго, потому что scan идёт снизу, приходится
просматривать полтаблицы
zhur на ppcdev% time perl -ME -e 'for (1..1000) {get_sql("select
SQL_NO_CACHE * from ipgeobase where istart <= 62432 and iend >= 62432
limit 1")}'
real    0m26.125s

если нужная запись есть, то с сортировкой istart desc работает быстро
zhur на ppcdev% time perl -ME -e 'for (1..1000) {get_sql("select
SQL_NO_CACHE * from ipgeobase where istart <= 62432 and iend >= 62432
order by istart desc limit 1")}'
real    0m0.264s

если нужной записи нет, то с сортировкой istart desc работает работает долго
zhur на ppcdev% time perl -ME -e 'for (1..1000) {get_sql("select
SQL_NO_CACHE * from ipgeobase where istart <= 62434 and iend >= 62434
order by istart desc limit 1")}'
real    0m27.418s


> Я просто сейчас тестирую на Pg это дело. Потом конечно смогу
> посмотреть на mysql, но от помощи не откажусь.
>
> 2009/12/1 Sergey Zhuravlev <sergey.zhuravlev на gmail.com>:
>> Мне кажется, оптимальным решением было бы избавиться от пересечений
>> сетей при загрузке базы в mysql.
>> После этого можно было бы делать
>> select * from ipgeobase where istart <= ? order by istart desc limit 1
>> и проверять iend >= $ip на стороне перла
>>
>> Проверил на не на реальной базе (лень загружать), но на подобных
>> тестовых данных:
>>
>> zhur на ppcdev% time perl -ME -e 'for (1..1000) {get_sql("select
>> SQL_NO_CACHE * from ipgeobase where istart <= 62432 and iend >= 62432
>> order by iend-istart asc limit 1")}'
>> real    0m27.686s
>>
>> zhur на ppcdev% time perl -ME -e 'for (1..1000) {get_sql("select
>> SQL_NO_CACHE * from ipgeobase where istart <= 62432 order by istart
>> desc limit 1")}'
>> real    0m0.256s
>>
>> Но для простого решения модуль конечно подходит и сейчас.
>> И он точно несравненно лучше того, что раздаётся с сайта ;-))
>>
>>
>> 2009/11/29 Ruslan Zakirov <ruslan.zakirov на gmail.com>:
>>> 2009/11/29 Sergey Zhuravlev <sergey.zhuravlev на gmail.com>:
>>>> Привет.
>>>>
>>>> Модуль клёвый.
>>>> Только запрос из intersections - это index range scan, в среднем на
>>>> половину таблички.
>>>
>>> Не уверен, что это будет половина таблички. Нужно посмотреть логи.
>>> Конечно для нагруженного пректа я бы сделал по другому. Разбил бы все
>>> на три структуры и индекс в памяти:
>>>
>>> my $index_length = 8;
>>> # индекс - массив из 2^$index_lenght элементов
>>> my @index = (
>>>   <индекс первого блока, где $index_lenght первых бит начала блока == 0>
>>>   <индекс первого блока, где $index_lenght первых бит начала блока == 1>
>>>   <индекс первого блока, где $index_lenght первых бит начала блока == 2>
>>>   ....
>>> );
>>>
>>> В зависимости от размера маски меняется объем используемой памяти.
>>>
>>> Уже с этого момента можно посылать в БД, то есть указатели у нас
>>> просто дополнят условия поиска, а можно в память смотреть:
>>>
>>> my @blocks = (
>>>  [start, end, coordinates],
>>> ...
>>> );
>>>
>>> my @coordinates = (
>>>  [long, lat, city],
>>>  ...
>>> );
>>>
>>> my @cities = (
>>>  [name, region, federal_district],
>>> );
>>>
>>>
>>> Есть лучше идеи?
>>>
>>>> На нагруженных проектах это может вызвать проблемы, хотя, в случае
>>>> mysql и 128'000 записей это достаточно быстро.
>>>
>>> Мне нужно было простое решение. Десяток поисков в день в окружении,
>>> где и так памяти не очень много.
>>>
>>>> 2009/11/29 Ruslan Zakirov <ruz на bestpractical.com>:
>>>>> Всем привет,
>>>>>
>>>>> Недавно мы обсуждали определение положения по IP адресу. Мне
>>>>> посоветовали БД от http://ipgeobase.ru.
>>>>>
>>>>> Я рад, что существует такой ресурс. Был немного удивлен примерами кода
>>>>> и очень удивлен структурой БД. Код на perl страшен, достаточно сделать
>>>>> для него perltidy и он уже становится читабельный. Алгоритм тоже не
>>>>> сахар, но это издержки структуры файла. Переключение на указание
>>>>> смещения вместо номеров строк, позволит сделать быстрый поиск прямо из
>>>>> файлов без полного сканирования или загрузки их в память.
>>>>>
>>>>> В итоге решил отказаться от работы с файлами и заливать все в табличку
>>>>> БД. Написал скрипт обновления БД и модуль для работы. Пока не на
>>>>> CPANе, но если не будет конструктивной критики и успешно уйдет в
>>>>> продакшн, то залью на цпан и в гитхаб.
>>>>>
>>>>> --
>>>>> Веселой гео локации, Руслан.
>>>>>
>>>>> --
>>>>> Moscow.pm mailing list
>>>>> moscow-pm на pm.org | http://moscow.pm.org
>>>>>
>>>>>
>>>> --
>>>> Moscow.pm mailing list
>>>> moscow-pm на pm.org | http://moscow.pm.org
>>>>
>>>
>>>
>>>
>>> --
>>> Best regards, Ruslan.
>>> --
>>> Moscow.pm mailing list
>>> moscow-pm на pm.org | http://moscow.pm.org
>>>
>> --
>> Moscow.pm mailing list
>> moscow-pm на pm.org | http://moscow.pm.org
>>
>
>
>
> --
> Best regards, Ruslan.
> --
> Moscow.pm mailing list
> moscow-pm на pm.org | http://moscow.pm.org
>


Подробная информация о списке рассылки Moscow-pm