Недавно стал использовать Sphinx. Столкнулся с задачей, решение, которой не нашел в документации.
Итак, задача: необходимо выполнять поиск в таблице с проверкой прав доступа, которые хранятся в другой таблице.
Как делаю сейчас:
1. индексирую таблицу с данными (1,5 млн записей)
2. при поиске от Sphinx'а получаю список ID
3. к этому списку делаю inner join c ID всех доступных пользователю записей (из таблицы security)
В текущем решении не устраивает:
1. нагружает СУБД
2. нужно чтобы поисковый сервер был максимально независим, чтобы при поиске сервер с данными нагружался по минимуму.
Возможное решение:
Создаем второй индекс прав доступа и при поиске объединяем результаты поиска из двух индексов (передаем дополнительно id пользователя).
Все зависит от того каким образом организованы эти права. У меня к примеру, права по группам. Индекс содержит атрибут sql_attr_multi = bigint usergroups from field. -1 все пользователи, далее группы: 0 анреги, 1, 2… Ну и потом ставлю фильтр при поиске [-1, curent_user_group].
По поводу организации прав доступа, есть таблицы (количество записей):
users — пользователи, 2000
groups — группы, 300
usersgroup — какой пользователь к какой группе относится, 4600 security — два поля с id пользователя или группы, и с id документа (к которому доступ определяем)
В таблице security 11 млн. записей.
Прочитал на счет sql_attr_multi — в теории должно сработать.
Настораживает два момента: 1. большое количество записей в security
2. придется каждый раз полностью обновлять в sphinx'е все данные из security
проверили на практике — все действительно работает как надо, несмотря на большие объемы данных.
Еще раз спасибо за ответ!
Рассматриваем еще один вариант реализации.
В текущем варианте, не устраивает лишь то что атрибуты всегда приходится перезаливать заново, а занимают они 1,5 Гига. Вот если бы можно было только изменения дописывать, было бы здорово.
В индексы sphinx можно поместить любой запрос. Я так понял, что inner join вы делаете вне sphinx. Так сделайте такой запрос, который из sphinx уже вернет только те id, на которые у юзера есть права и все.
Конечно, структуру вашей бд я не знаю, но если есть возможность обойтись без join'a — лучше это сделать.
А так пользователь karenishe прав. Сделайте запрос в самом теле source'a поиском сразу с запросом и в таблицу прав.
А-ля: sql_query= SELECT * FROM first_table INNER JOIN users ON…
Ниже написал по подробнее о структуре БД.
В таблице прав доступа содержится 11 млн. записей, если все это дело с джоинить с данными (1,5 млн. записей), то получится большой индекс — из 11 млн. записей.
Или все нормально? Не такой уж и большой для сфинкса?