Нагруженный поиск на Sphinx


   Роман Павлушко                              Михаил Тюрин
   rpavlushko@avito.ru                         mtyurin@avito.ru




 Sphinx User Conference 2011, St. Petersburg
о проекте


•     60М запросов в сутки (AVITO, TORG, API)
•     80К запросов в минуту
•     75К пользователей online
•     50М объявлений всего
•     4М активных объявлений
•     150К новых объявлений в сутки
•     10 новых объявлений в секунду в пики



       Sphinx User Conference 2011, St. Petersburg
распределение просмотров на сайте




                                                  88%
                                                  запросов
                                                   связаны
                                                 с поиском!




   Sphinx User Conference 2011, St. Petersburg
динамика роста


                       постоянный рост
req/day, M




             Sphinx User Conference 2011, St. Petersburg
используемые технологии


Web-server                 nginx
Application                php-fpm + eaccelerator
DB                         postgresql + pgbouncer + londiste
NoSQL                      redis
Search Engine              sphinx
Cache/Session              memcached + magent
Monitoring                 munin, monit, bash
...                        git, python, etc


      Sphinx User Conference 2011, St. Petersburg
powered by sphinx



●   поиск по объявлениям (сайт, api)
●   поиск похожих объявлений

●   автодополнение (suggest)


●   поиск по полной базе объявлений
●   внутренняя статистика




       Sphinx User Conference 2011, St. Petersburg
поиск по объявлениям



1

2




3
                                                     5




4




       Sphinx User Conference 2011, St. Petersburg
похожие объявления




                                                 каскад




   Sphinx User Conference 2011, St. Petersburg
поиск по объявлениям / цифры

•    80М запросов в сутки
•    1700 запросов в секунду в пики
•    4М документов в индексе
•    размер индексов 2GB
•    46 индексов (основной + категории)
•    каждые 10 минут полная переиндексация
•    8 серверов (x16 core)
•    69% запросов без query (43 vs 22 ms)


       Sphinx User Conference 2011, St. Petersburg
поиск по объявлениям / скорость




                                    Query Time




   Sphinx User Conference 2011, St. Petersburg
поиск по объявлениям / offset




                               первые 50 страниц   99%



                                       Page




   Sphinx User Conference 2011, St. Petersburg
поиск по объявлениям / архитектура


                                      clients



                                   sphinxql

M          S1        S2          S3          S4     S5       S6   S7

                                      deploy



                                                    DB
 indexer           repca            londiste      master 1




    Sphinx User Conference 2011, St. Petersburg
поиск по объявлениям / клиенты

•    API SphinxQL
•    lazy initialization
•    по возможности используем multi-query
•    вычисляем оптимальный max_matches
•    кешируем поисковую выдачу на 1 минуту
•    кешируем похожие объявления до ближайшей
     переиндексации
•    берем из sphinx только ID документов


        Sphinx User Conference 2011, St. Petersburg
поиск по объявлениям / настройки sphinx

•    отдельные конфиги для индексатора и поиска
•    workers = prefork threads (проблемы с HUP!)
•    отказ от MVA, на каждый фильтр свой атрибут
•    на каждую категорию свой индекс
•    дисковые индексы без дельты* хранятся в RAM
•    отказ от query_log
•    настройки под характеристики железа
     (max_children, read_buffer, read_unhinted, etc)


       Sphinx User Conference 2011, St. Petersburg
поиск по объявлениям / требования


•    tmax < 30 минут

     •   время на применение услуг к объявлению
     •   время на премодерацию
     •   время на переиндексацию
•    сохранить быстрые настройки поиска
•    поддержать целостность данных
•    решить проблему селективности выборки из БД



         Sphinx User Conference 2011, St. Petersburg
построение
                                                снапшота – 18 с
                                                                                                   индексация




                                                 многопоточная
                                                    индексация


                                                 items_full – 515 с
                                               items_cat* – 380 c




Sphinx User Conference 2011, St. Petersburg
                                                                      время переиндексации 11:40




                                                деплой индексов
                                              на слейвы – 120 с

                                                деплой мастера
                                                и ротация – 35 с
индексация / хранение объявлений


•    одна большая база, одна большая таблица ― всё
     очень страшно
•    но! ― всё работает: OLTP, index scan (1K+ / sec)


•    1K+ req / sec, выдача до 50 Mbit / sec


•    упирались в кеш / диcк



       Sphinx User Conference 2011, St. Petersburg
индексация / хранение объявлений




•    MV -- materialized view, "хитрые" триггеры
•    repca и londiste с небольшим патчем
•    конфиги pg: master ― размазывем io, repca ―
     "in-memory pg", version: 9.1.1
•    pgbouncer 'ы : разные пулы под разные задачи
     (сайт, индексация, мониторинг, сервисы)




       Sphinx User Conference 2011, St. Petersburg
индексация / репликация дла снапшота




   Sphinx User Conference 2011, St. Petersburg
индексация


1.1) mv триггеры ( 9.0 )
   create constraint trigger имя_триггера
          after список_событий on таблица_связанная_с_mv
          deferrable initially deferred
          for each row execute procedure repca.mv_refresh_trg();



1.2) mv рефреш функция
   CREATE OR REPLACE FUNCTION repca.mv_refresh_trg() RETURNS trigger AS
   $$
          begin
                  delete from repca.items_mv mv where ( mv.item_id = OLD.item_id );
                  insert into repca.items_mv select * from repca.items_v v where ( v.item_id = OLD.item_id );
                  return null;
          end;
   $$
   LANGUAGE 'plpgsql';




        Sphinx User Conference 2011, St. Petersburg
индексация / построение снапшота

•    сфинксы вызывают базу + psql
•    транзакция построения ss
•    а в ней функция построения ss
•    таблицы и hstore, оверхед hstore: 14 sec / 10M
•    параллельное вычитывание ss
•    ! seq scan из shared buffers


* ss - снапшот / snapshot


       Sphinx User Conference 2011, St. Petersburg
индексация

2) построение снапшота
   begin;
            set transaction isolation level serializable;
            select sphinx.x_prepare_active_items({{ idx }});
   end;




3) hstore
   select
            ...
            (x.tag -> 'val188')::smallint as val188,
            (x.tag -> 'val187')::smallint as val187,
            (x.tag -> 'val184')::smallint as val184,
            ...
   from sphinx.x_a_v_i1 x
   where x.category_id = 15




      Sphinx User Conference 2011, St. Petersburg
индексация

create view repca.items_v as
select
       ....
       ix.item_id                       as item_id,
       ...
       sphinx.x_get_pure_params         (
               case ix.category_id
       when 9 then (select hstore(cx.*) from options.category_9    cx where cx.active and (cx.item_id = ix.item_id))
       when 10 then (select hstore(cx.*) from options.category_10 cx where cx.active and (cx.item_id = ix.item_id))
       when 11 then (select hstore(cx.*) from options.category_11 cx where cx.active and (cx.item_id = ix.item_id))
         ...
       when 109 then (select hstore(cx.*) from options.category_109 cx where cx.active and (cx.item_id = ix.item_id))
               end
       ) as tag_params
from
       items ix ....
where
       ( ix.active ) and ( .... )




                 Sphinx User Conference 2011, St. Petersburg
индексация / база в памяти

pg_buffercache b
  inner join pg_class c on ( b.relfilenode = pg_relation_filenode(c.oid) )

rel                    buffers_mb    rel_mb    all in
                                               memory

items_mv               2359          2358      100 %    seq scan и фильтры,
                                                        вычитка через вьюшку-
                                                        запрос

x_a_v_i1               2202          2201      100 %    снапшот -- ! seq scan Ы

items_mv_pkey          266           266       100 %    так как londiste

pg_toast_91311         26            26        100 %

pg_toast_19818921      24            24        100 %

pg_toast_2619          9             9         100 %

pg_toast_91311_index   2             2         100 %




      Sphinx User Conference 2011, St. Petersburg
индексация / фрагментация


select * from pgstattuple(...)   repca.items_mv     sphinx.x_a_v_i1    repca.items_mv_pkey

table_len                            2473418752           2309922816            282746880

tuple_count                              4228442            4226761                4249388

tuple_len                            2246676901           2243321710              67990208

tuple_percent                               90.83              97.12                 24.05

dead_tuple_count                            5639                  0                   8819

dead_tuple_len                           3135978                  0                 141104

dead_tuple_percent                           0.13                 0                   0.05

free_space                            178386236            27080140             194390312

free_percent                                 7.12               1.17                 68.75




            Sphinx User Conference 2011, St. Petersburg
индексация / время построения и чтения




•    psql ... -c 'begin; [строим_снапшот]; end;' (18 с)
•    в 9.2 не надо будет строить таблицу в принципе
•    можно будет из сессии экспортировать
     транзакционный снапшот из mvcc




       Sphinx User Conference 2011, St. Petersburg
индексация / время построения и чтения


explain (analyze, buffers)
 select * from sphinx.x_a_v_i1;

"Seq Scan on x_a_v_i1 (cost=0.00..293363.20 rows=11283200 width=172)
(actual time=0.014..4880.666 rows=4229686 loops=1)"
" Buffers: shared hit=282080"
"Total runtime: 8996.531 ms"

explain (analyze, buffers)
 select * from sphinx.x_a_v_i1 where category_id = 27 -- 27 - "шмотки" -- фильтр-предикат
на категорию

"Seq Scan on x_a_v_i1 (cost=0.00..296876.50 rows=56440 width=172) (actual time=0.044..
3593.978 rows=712912 loops=1)"
" Filter: (category_id = 27)"
" Buffers: shared hit=282202"
"Total runtime: 4308.269 ms"




      Sphinx User Conference 2011, St. Petersburg
рост БД - НО постоянный хитрейт




   Sphinx User Conference 2011, St. Petersburg
io мастера теперь не влияет на индексацию




   Sphinx User Conference 2011, St. Petersburg
backoffice




                                                  E D
                        O R
                     N S
      C E
    Sphinx User Conference 2011, St. Petersburg
backoffice / архитектура



                        1
                             1                                            4/4/16
                   1
            Pool



                                                                      3
                                                              3
                                                      3
                                            Group 1




                                                          3
                                             3                    4
   Node 1          Node 2          Node 3             Node 4




   Sphinx User Conference 2011, St. Petersburg
backoffice / цифры


•    50M документов в индексе
•    размер индексов 16GB
•    8 серверов
•    16 нод (по 2 на сервер)
•    ежеминутная индексация
•    раз в час мерж дельты
•    нагрузки нет (в среднем 30 запросов в минуту)



       Sphinx User Conference 2011, St. Petersburg
backoffice / реализация



•    основной индекс + дельта
•    MVA для поиска по параметрам категории
•    дельта по last_update_txtime с нахлестом
•    3 уровня - ноды/группа/pool
•    приложение для управления конфигурацией
•    медленная полная переиндексация




       Sphinx User Conference 2011, St. Petersburg
backoffice / время индексации




   Sphinx User Conference 2011, St. Petersburg
автодополнение (suggest)




   Sphinx User Conference 2011, St. Petersburg
автодополнение

•    обновляем индекс раз в неделю
•    source: парсим access_log в БД
•    чистим мусор (not found, stop words)
•    вычисляем популярные запросы (order by rank)
•    enable_star = 1 ― ищем по маске
•    sql_attr_string ― храним фразу в sphinx
•    учитываем категорию при поиске
•    кеш работает (~1% запросов к sphinx)


       Sphinx User Conference 2011, St. Petersburg
автодополнение / цифры


•    размер индекса - 25MВ :)
•    200K документов в индексе
•    1M запросов в сутки (кеш работает)
•    среднее время выполнения запроса - 0.0003 s!


     Почему suggest сделан на sphinx?
     Потому что разработка бекенда заняла день,
     и это прекрасно работает


       Sphinx User Conference 2011, St. Petersburg
cпасибо!
                   вопросы?

 Роман Павлушко                               Михаил Тюрин
 rpavlushko@avito.ru                          mtyurin@avito.ru
 @pavlushko




Sphinx User Conference 2011, St. Petersburg

Нагруженный поиск на Sphinx

  • 1.
    Нагруженный поиск наSphinx Роман Павлушко Михаил Тюрин rpavlushko@avito.ru mtyurin@avito.ru Sphinx User Conference 2011, St. Petersburg
  • 2.
    о проекте • 60М запросов в сутки (AVITO, TORG, API) • 80К запросов в минуту • 75К пользователей online • 50М объявлений всего • 4М активных объявлений • 150К новых объявлений в сутки • 10 новых объявлений в секунду в пики Sphinx User Conference 2011, St. Petersburg
  • 3.
    распределение просмотров насайте 88% запросов связаны с поиском! Sphinx User Conference 2011, St. Petersburg
  • 4.
    динамика роста постоянный рост req/day, M Sphinx User Conference 2011, St. Petersburg
  • 5.
    используемые технологии Web-server nginx Application php-fpm + eaccelerator DB postgresql + pgbouncer + londiste NoSQL redis Search Engine sphinx Cache/Session memcached + magent Monitoring munin, monit, bash ... git, python, etc Sphinx User Conference 2011, St. Petersburg
  • 6.
    powered by sphinx ● поиск по объявлениям (сайт, api) ● поиск похожих объявлений ● автодополнение (suggest) ● поиск по полной базе объявлений ● внутренняя статистика Sphinx User Conference 2011, St. Petersburg
  • 7.
    поиск по объявлениям 1 2 3 5 4 Sphinx User Conference 2011, St. Petersburg
  • 8.
    похожие объявления каскад Sphinx User Conference 2011, St. Petersburg
  • 9.
    поиск по объявлениям/ цифры • 80М запросов в сутки • 1700 запросов в секунду в пики • 4М документов в индексе • размер индексов 2GB • 46 индексов (основной + категории) • каждые 10 минут полная переиндексация • 8 серверов (x16 core) • 69% запросов без query (43 vs 22 ms) Sphinx User Conference 2011, St. Petersburg
  • 10.
    поиск по объявлениям/ скорость Query Time Sphinx User Conference 2011, St. Petersburg
  • 11.
    поиск по объявлениям/ offset первые 50 страниц 99% Page Sphinx User Conference 2011, St. Petersburg
  • 12.
    поиск по объявлениям/ архитектура clients sphinxql M S1 S2 S3 S4 S5 S6 S7 deploy DB indexer repca londiste master 1 Sphinx User Conference 2011, St. Petersburg
  • 13.
    поиск по объявлениям/ клиенты • API SphinxQL • lazy initialization • по возможности используем multi-query • вычисляем оптимальный max_matches • кешируем поисковую выдачу на 1 минуту • кешируем похожие объявления до ближайшей переиндексации • берем из sphinx только ID документов Sphinx User Conference 2011, St. Petersburg
  • 14.
    поиск по объявлениям/ настройки sphinx • отдельные конфиги для индексатора и поиска • workers = prefork threads (проблемы с HUP!) • отказ от MVA, на каждый фильтр свой атрибут • на каждую категорию свой индекс • дисковые индексы без дельты* хранятся в RAM • отказ от query_log • настройки под характеристики железа (max_children, read_buffer, read_unhinted, etc) Sphinx User Conference 2011, St. Petersburg
  • 15.
    поиск по объявлениям/ требования • tmax < 30 минут • время на применение услуг к объявлению • время на премодерацию • время на переиндексацию • сохранить быстрые настройки поиска • поддержать целостность данных • решить проблему селективности выборки из БД Sphinx User Conference 2011, St. Petersburg
  • 16.
    построение снапшота – 18 с индексация многопоточная индексация items_full – 515 с items_cat* – 380 c Sphinx User Conference 2011, St. Petersburg время переиндексации 11:40 деплой индексов на слейвы – 120 с деплой мастера и ротация – 35 с
  • 17.
    индексация / хранениеобъявлений • одна большая база, одна большая таблица ― всё очень страшно • но! ― всё работает: OLTP, index scan (1K+ / sec) • 1K+ req / sec, выдача до 50 Mbit / sec • упирались в кеш / диcк Sphinx User Conference 2011, St. Petersburg
  • 18.
    индексация / хранениеобъявлений • MV -- materialized view, "хитрые" триггеры • repca и londiste с небольшим патчем • конфиги pg: master ― размазывем io, repca ― "in-memory pg", version: 9.1.1 • pgbouncer 'ы : разные пулы под разные задачи (сайт, индексация, мониторинг, сервисы) Sphinx User Conference 2011, St. Petersburg
  • 19.
    индексация / репликациядла снапшота Sphinx User Conference 2011, St. Petersburg
  • 20.
    индексация 1.1) mv триггеры( 9.0 ) create constraint trigger имя_триггера after список_событий on таблица_связанная_с_mv deferrable initially deferred for each row execute procedure repca.mv_refresh_trg(); 1.2) mv рефреш функция CREATE OR REPLACE FUNCTION repca.mv_refresh_trg() RETURNS trigger AS $$ begin delete from repca.items_mv mv where ( mv.item_id = OLD.item_id ); insert into repca.items_mv select * from repca.items_v v where ( v.item_id = OLD.item_id ); return null; end; $$ LANGUAGE 'plpgsql'; Sphinx User Conference 2011, St. Petersburg
  • 21.
    индексация / построениеснапшота • сфинксы вызывают базу + psql • транзакция построения ss • а в ней функция построения ss • таблицы и hstore, оверхед hstore: 14 sec / 10M • параллельное вычитывание ss • ! seq scan из shared buffers * ss - снапшот / snapshot Sphinx User Conference 2011, St. Petersburg
  • 22.
    индексация 2) построение снапшота begin; set transaction isolation level serializable; select sphinx.x_prepare_active_items({{ idx }}); end; 3) hstore select ... (x.tag -> 'val188')::smallint as val188, (x.tag -> 'val187')::smallint as val187, (x.tag -> 'val184')::smallint as val184, ... from sphinx.x_a_v_i1 x where x.category_id = 15 Sphinx User Conference 2011, St. Petersburg
  • 23.
    индексация create view repca.items_vas select .... ix.item_id as item_id, ... sphinx.x_get_pure_params ( case ix.category_id when 9 then (select hstore(cx.*) from options.category_9 cx where cx.active and (cx.item_id = ix.item_id)) when 10 then (select hstore(cx.*) from options.category_10 cx where cx.active and (cx.item_id = ix.item_id)) when 11 then (select hstore(cx.*) from options.category_11 cx where cx.active and (cx.item_id = ix.item_id)) ... when 109 then (select hstore(cx.*) from options.category_109 cx where cx.active and (cx.item_id = ix.item_id)) end ) as tag_params from items ix .... where ( ix.active ) and ( .... ) Sphinx User Conference 2011, St. Petersburg
  • 24.
    индексация / базав памяти pg_buffercache b inner join pg_class c on ( b.relfilenode = pg_relation_filenode(c.oid) ) rel buffers_mb rel_mb all in memory items_mv 2359 2358 100 % seq scan и фильтры, вычитка через вьюшку- запрос x_a_v_i1 2202 2201 100 % снапшот -- ! seq scan Ы items_mv_pkey 266 266 100 % так как londiste pg_toast_91311 26 26 100 % pg_toast_19818921 24 24 100 % pg_toast_2619 9 9 100 % pg_toast_91311_index 2 2 100 % Sphinx User Conference 2011, St. Petersburg
  • 25.
    индексация / фрагментация select* from pgstattuple(...) repca.items_mv sphinx.x_a_v_i1 repca.items_mv_pkey table_len 2473418752 2309922816 282746880 tuple_count 4228442 4226761 4249388 tuple_len 2246676901 2243321710 67990208 tuple_percent 90.83 97.12 24.05 dead_tuple_count 5639 0 8819 dead_tuple_len 3135978 0 141104 dead_tuple_percent 0.13 0 0.05 free_space 178386236 27080140 194390312 free_percent 7.12 1.17 68.75 Sphinx User Conference 2011, St. Petersburg
  • 26.
    индексация / времяпостроения и чтения • psql ... -c 'begin; [строим_снапшот]; end;' (18 с) • в 9.2 не надо будет строить таблицу в принципе • можно будет из сессии экспортировать транзакционный снапшот из mvcc Sphinx User Conference 2011, St. Petersburg
  • 27.
    индексация / времяпостроения и чтения explain (analyze, buffers) select * from sphinx.x_a_v_i1; "Seq Scan on x_a_v_i1 (cost=0.00..293363.20 rows=11283200 width=172) (actual time=0.014..4880.666 rows=4229686 loops=1)" " Buffers: shared hit=282080" "Total runtime: 8996.531 ms" explain (analyze, buffers) select * from sphinx.x_a_v_i1 where category_id = 27 -- 27 - "шмотки" -- фильтр-предикат на категорию "Seq Scan on x_a_v_i1 (cost=0.00..296876.50 rows=56440 width=172) (actual time=0.044.. 3593.978 rows=712912 loops=1)" " Filter: (category_id = 27)" " Buffers: shared hit=282202" "Total runtime: 4308.269 ms" Sphinx User Conference 2011, St. Petersburg
  • 28.
    рост БД -НО постоянный хитрейт Sphinx User Conference 2011, St. Petersburg
  • 29.
    io мастера теперьне влияет на индексацию Sphinx User Conference 2011, St. Petersburg
  • 30.
    backoffice E D O R N S C E Sphinx User Conference 2011, St. Petersburg
  • 31.
    backoffice / архитектура 1 1 4/4/16 1 Pool 3 3 3 Group 1 3 3 4 Node 1 Node 2 Node 3 Node 4 Sphinx User Conference 2011, St. Petersburg
  • 32.
    backoffice / цифры • 50M документов в индексе • размер индексов 16GB • 8 серверов • 16 нод (по 2 на сервер) • ежеминутная индексация • раз в час мерж дельты • нагрузки нет (в среднем 30 запросов в минуту) Sphinx User Conference 2011, St. Petersburg
  • 33.
    backoffice / реализация • основной индекс + дельта • MVA для поиска по параметрам категории • дельта по last_update_txtime с нахлестом • 3 уровня - ноды/группа/pool • приложение для управления конфигурацией • медленная полная переиндексация Sphinx User Conference 2011, St. Petersburg
  • 34.
    backoffice / времяиндексации Sphinx User Conference 2011, St. Petersburg
  • 35.
    автодополнение (suggest) Sphinx User Conference 2011, St. Petersburg
  • 36.
    автодополнение • обновляем индекс раз в неделю • source: парсим access_log в БД • чистим мусор (not found, stop words) • вычисляем популярные запросы (order by rank) • enable_star = 1 ― ищем по маске • sql_attr_string ― храним фразу в sphinx • учитываем категорию при поиске • кеш работает (~1% запросов к sphinx) Sphinx User Conference 2011, St. Petersburg
  • 37.
    автодополнение / цифры • размер индекса - 25MВ :) • 200K документов в индексе • 1M запросов в сутки (кеш работает) • среднее время выполнения запроса - 0.0003 s! Почему suggest сделан на sphinx? Потому что разработка бекенда заняла день, и это прекрасно работает Sphinx User Conference 2011, St. Petersburg
  • 38.
    cпасибо! вопросы? Роман Павлушко Михаил Тюрин rpavlushko@avito.ru mtyurin@avito.ru @pavlushko Sphinx User Conference 2011, St. Petersburg