sphinx-delta

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

К примеру, мы имеем очень много записей в базе данных, сотни тысяч или несколько миллионов записей, и данные поступают очень часто, нам их необходимо индексировать, однако запускать каждые 5-10 минут индексацию — это слишком трудоемко.

Поэтому мы делаем два индекса:

  • Полный — индексируются все данные целиком (запускаем раз в сутки)
  • Дельта — индексируется только малая часть данных, добавленных в течении дня (запускаем каждые 5-10 минут)

Но как определять с какого момента индексировать данные в дельта-индексе?

Нам необходимо помнить крайний проиндексированный ид-записи из полного-индекса, и начинать индексировать данные только с него, все очень просто :)

Для этого создадим еще одну таблицу в базе данных, чтобы хранить там ид крайней записи из полного-индекса:

1
2
3
4
CREATE TABLE `sphinx_delta_counter` (
    `index_name` ENUM( 'pyha_forum' ) NOT NULL,
    `last_post_id` INT UNSIGNED NOT NULL
) ENGINE = InnoDB;

Где,

  • «index_name» — имя индекса, например если у вас много индексов с разных таблиц (можно опустить, если у вас один индекс);
  • «last_post_id» — крайний номер записи для конкретного индекса.

Вставим для нашего индекса запись, чтобы потом можно было обновлять счетчик:

1
2
INSERT INTO `sphinx_delta_counter`
    SET `index_name` = 'pyha_forum', `last_post_id` = 0;

Вы конечно можете этот запрос и в индексе сфинкса использовать, предварительно переписав его на «on duplicate key» и добавив уникальный индекс на связку «index_name+last_post_id», однако я думаю это излишне.

Строим индексы в Sphinx

Привожу примерный конфигурационный файл, на примере предыдущей статьи http://adw0rd.ru/2009/smf-sphinx/.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# сорс для подключения к БД, далее его будем наследовать в других сорсах
source dbconnect
{
    type = mysql
    sql_host = localhost
    sql_user = pyha
    sql_pass =
    sql_db = pyha
    sql_port = 3306
    sql_sock = /tmp/mysql.sock

}

# сорс полного-индекса
source pyha_forum : dbconnect
{

    sql_query_pre = SET NAMES utf8
    sql_query_pre = SET CHARACTER SET utf8

    # обновляем наш счетчик, добавляем туда крайний ид записи для дельта-индекса
    sql_query_pre = \
        update sphinx_delta_counter \
        set last_post_id = (select max(ID_MSG) from smf_messages) \
        where index_name = 'pyha_forum';

    # выбираем все данные для полного-индекса
    sql_query = \
        select ID_MSG, concat('user:',posterName) as posterName, subject, body \
        from smf_messages;

    sql_query_info = select ID_MSG, posterName, subject, body from smf_messages where ID_MSG = $id
    sql_ranged_throttle = 0
}

# сорс дельта-индекса
source pyha_forum_delta : dbconnect
{

    sql_query_pre = SET NAMES utf8
    sql_query_pre = SET CHARACTER SET utf8

    # выбираем только те данные, которые появились после проиндексации полного-индекса
    sql_query = \
        select ID_MSG, concat('user:',posterName) as posterName, subject, body \
        from smf_messages \
        where ID_MSG > (select last_post_id from sphinx_delta_counter where index_name = 'pyha_forum');

    sql_query_info = select ID_MSG, posterName, subject, body from smf_messages where ID_MSG = $id
    sql_ranged_throttle = 0
}

# полный-индекс
index pyha_forum
{
    source = pyha_forum
    path = /var/sphinxsearch/pyha_forum

    docinfo = extern
    mlock = 0
    morphology = stem_enru
    min_word_len = 2
    charset_type = utf-8
    charset_table = 0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F
    min_infix_len = 2
    enable_star = 1
}

# дельта-индекс
index pyha_forum_delta : pyha_forum
{
    source = pyha_forum_delta
    path = /var/sphinxsearch/pyha_forum_delta
}

# настройки индексатора
indexer
{
    mem_limit = 32M
}

# настройки поискового демона
searchd
{
    address = 127.0.0.1
    port = 3312
    log = /var/sphinxsearch/log/searchd.log
    query_log = /var/sphinxsearch/log/query.log
    read_timeout = 5
    max_children = 30
    #pid_file = /var/sphinxsearch/log/searchd.pid
    max_matches = 1000
}

Ну вот и все, сфинкс настроен, далее поставим переиндексацию в крон.

Ставим в крон

1
2
0 1 * * * /usr/local/bin/indexer --config /usr/local/etc/sphinx.conf.sh pyha_forum --rotate > /dev/null
*/5 * * * * /usr/local/bin/indexer --config /usr/local/etc/sphinx.conf.sh pyha_forum_delta --rotate > /dev/null

Где,

  1. Индексировать полный-индекс каждый день в час ночи
  2. Индексировать дельта-индекс каждые пять минут

Не понятно что за конфиг «/usr/local/etc/sphinx.conf.sh»?
Тогда, читаем статью Инклуд конфигов Sphinx.

Добавим поиск по дельта-индексу в код

Так как я использую SphinxSE, то добавить надо так:

`query` = "поисковый запрос;index=pyha_forum,pyha_forum_delta"

Тогда будет производится поиск по полному- и дельта-индексам!

Встраиваем в SMF

Далее, раз мы разбираем пример на основе статьи http://adw0rd.ru/2009/smf-sphinx/, то снова найдем код в «/Source/Search.php» (строка ~1377):

1
2
3
4
5
6
7
$request = db_query(
   "SELECT `sm`.`ID_TOPIC`, `ssm`.`id` AS `ID_MSG`, 1000 AS `relevance`, 0 AS `num_matches`
    FROM `sphinx_smf_messages` AS `ssm`
    LEFT JOIN `smf_messages` AS `sm`
        ON `ssm`.`id` = `sm`.`ID_MSG`
    WHERE `ssm`.`query` = '"
.$context['search_params']['search'].";weights=1,2,3'
    LIMIT "
. (int) $_REQUEST['start'] . ", $modSettings[search_results_per_page]", __FILE__, __LINE__);

заменим на

1
2
3
4
5
6
7
$request = db_query(
   "SELECT `sm`.`ID_TOPIC`, `ssm`.`id` AS `ID_MSG`, 1000 AS `relevance`, 0 AS `num_matches`
    FROM `sphinx_smf_messages` AS `ssm`
    LEFT JOIN `smf_messages` AS `sm`
        ON `ssm`.`id` = `sm`.`ID_MSG`
    WHERE `ssm`.`query` = '"
.$context['search_params']['search'].";weights=1,2,3;index=pyha_forum,pyha_forum_delta'
    LIMIT "
. (int) $_REQUEST['start'] . ", $modSettings[search_results_per_page]", __FILE__, __LINE__);

Ну вот и все :)


Комментарии (13) на запись «Sphinx. Для чего нужны дельта-индексы и как их готовить?»

» Трекбеки скрыты, показать их?
  1. Михаил | 31.07.2009 в 16:48

    Что вы так боитесь использовать слово последний? суеверия =)

  2. adw0rd | 31.07.2009 в 18:57

    Я служил в Военно-Морской Авиации, там слово «последний» — нет, потомучто «последний вылет». Вот там из меня и выбили это слово ;)

  3. vill | 23.08.2009 в 00:17

    а ларчик просто открывался... Спасибо за информацию))

  4. Gena | 28.08.2009 в 02:32

    удобно проиндексировать только часть страницы, которая тебе нужна и на выходе получить максимальный результат

  5. Snowcore | 09.10.2009 в 20:37

    Хочу посоветоваться. Есть ли смысл создавать дельта индексы, если полная индексация системы происходит примерно за 3-4 минуты?

  6. adw0rd | 09.10.2009 в 20:47

    думаю нет, по крайней мере я бы не заморачивался...

    хотя если вам надо индексировать каждую минуту, то можно подумать о дельте...

    У вас ротейт идет 3-4 минуты?

  7. Elvis | 17.03.2010 в 17:46

    Доброе время суток, я вот делал по такому алгоритму строю дельта индекс, там появились новые индексы, потом добавляю их в основной индекс с помощью --merge , в принципе все отлично, но хотел бы Вас спросить можно ли как то удалять индексы из дельта индекса после слияния в основной ? заранее всех благодарю!

  8. Elvis | 19.03.2010 в 10:35

    Спасибо разобрался! :)

  9. adw0rd | 19.03.2010 в 11:42

    Elvis, как решили?

  10. Grind | 17.04.2010 в 11:28

    Разве счётчик нада обновлять не в сорсе дельта индекса ?

  11. adw0rd | 17.04.2010 в 13:10

    Grind, а на основании чего вы так решили?

  12. Grind | 17.04.2010 в 16:26

    Предпологал, что после каждой дельта индексации происходит изменение индекса, для последующей индексации от этого id.

  13. adw0rd | 17.04.2010 в 19:43

    >Предпологал, что после каждой дельта индексации происходит изменение индекса

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

    А вот после индексации основного-индекса запоминается максимальный проиндексированный ид, и с него начинает дельта-индекс индексировать данные

Оставить комментарий


Часто требуется раскрутка сайта и для создания нового бизнеса с минимальными затратами.