Как увеличить скорость поиска в sphinx?

Имеется база данных MySQL, размером 200 Гб. 4 млрд текстовых записей + ID (AUTO_INCREMENT).
Если делать простой запрос LIKE '%%', то он длится примерно 10 часов.
Я поставил Sphinx, проиндексировал, получилось 600 ГБ индекс(пришлось покупать еще один HDD). Теперь запрос идет от 5 до 10 минут. Все равно долго. Сейчас база поделена шарды, каждый шард по 32 млн документов(почему-то ограничение в 4 ГБ на 1 индекс).
Подскажите, кто в теме, что можно подкрутить, чтобы увеличить скорость поиска?
Конфиг файл:
#!/usr/bin/php
<?php
$nPerShard = 32*1000*1000;//32M
$shardCount = 120;
for ($i=0; $i<$shardCount; ++$i) { $first = $i*$nPerShard; $last = $first+$nPerShard; 
?>
source shard<?=$i?>
{
	type			= mysql

	sql_host		= localhost
	sql_user		= root
	sql_pass		= пароль
	sql_db			= база
	sql_port		= 3306

	sql_query_pre		= SET NAMES utf8

	sql_query		= SELECT ID, TEXT FROM таблица WHERE ID >= <?= $first ?> AND ID < <?= $last ?>

	sql_field_string	= TEXT
}

index idx_eng_keywords<?=$i?>
{
	source			= shard<?=$i?>

        wordforms		= /home/***/***/wordforms/en.txt
	path			= /media/***/c2dcfc1c-1656-4f82-b9fb-64a22058a278/eng-keywords-idx.<?=$i?>

#https://habrahabr.ru/post/147745/
	expand_keywords		= 1
	index_exact_words	= 1
}

<?php
}
?>


index index_main
{
	type           		= distributed

<?php for ($i=0; $i<$shardCount; ++$i) { ?>
	local			= idx_eng_keywords<?=$i?>

<?php } ?>

}


indexer
{
	mem_limit 		= 1024M
}


searchd
{
	listen			= 9312
	listen			= 9306:mysql41
	log			= /home/bogdan/poisk/sph/var/log/searchd-k.log
	query_log		= /home/bogdan/poisk/sph/var/log/query-k.log
	binlog_path		= # disable logging
	read_timeout		= 5
	max_children		= 30
	pid_file		= /home/bogdan/poisk/sph/var/log/searchd-k.pid
	seamless_rotate		= 1
	preopen_indexes		= 1
	unlink_old		= 1
	workers			= threads # for RT to work
	binlog_path		= /home/bogdan/poisk/sph/var/data
	dist_threads		= 8
}

* - файл словоформ весит 1.8 Мб.
Пример запроса, который производится (sphinxql):
SELECT * FROM index_main WHERE MATCH('test');
P.s. хотелось бы получать ВСЕ результаты поиска за 10 и меньше секунд, а не за 5 минут, как сейчас.
Информация о машине:
AMD процессор 8 ядер по 4 ГГц, 8 Гб памяти, 3 жестких диска(2 HDD: 320gb, 750gb; 1 SSD: 120gb),
Debian Linux 8.8.

===========
root@debian:/home/bogdan/poisk/sph/bin# hdparm -Tt /dev/sdc

/dev/sdc:
 Timing cached reads:   4440 MB in  2.00 seconds = 2220.46 MB/sec
 Timing buffered disk reads:  14 MB in  3.12 seconds =   4.49 MB/sec
root@debian:/home/bogdan/poisk/sph/bin# hdparm -Tt /dev/sdc

/dev/sdc:
 Timing cached reads:   5266 MB in  2.00 seconds = 2633.95 MB/sec
 Timing buffered disk reads:   8 MB in  3.45 seconds =   2.32 MB/sec
root@debian:/home/bogdan/poisk/sph/bin#


UPD 2 Jul 2017:
Убрал из конфига "sql_field_string = TEXT", поле в выборке(результате поиска) пропало, т.е. только айди выдает, но размер индекса стал 70 Гб. Время поиска 1 секунда на HDD, 0.4 сек на SSD.
Кто-то может объяснить, зачем нужен sql_field_string??
  • Вопрос задан
  • 2944 просмотра
Решения вопроса 2
@Fortop
Tech/Team lead
  • Увеличиваем память до 256, а лучше еще больше.
  • Разносим индексы на разные машины ( у Sphinx есть возможность подключать агентов)
  • Даже в рамках одной машины настраиваем количество агентов поиска равное количеству потоков которые может выполнять сервер (например 4хядерный процессор с HyperThreading = 8 потоков
  • Уточняем срок обновления индекса. Кешируем результаты поиска на отдельном сервере в мемкеш/файлы.


Все эти рецепты можно применять как по-отдельности, так и совместно.
Конкретные цифры с количеством машин, агентов поиска, объема памяти под индексы и под кеш нужно высчитывать в зависимости от конкретного решения.
Ответ написан
@crazy_racoon
все просто, ты использовал конструкцию, sql_field_string = TEXT, то есть ты добавил все поля из базы из этой колонки в поиск, соответственно поиск все засунул без изменений в индекс, и он стал жирным. убирай это. сделай поиск без этого, а уже результаты цепляй из базы, получится один запрос в базу со всем твоим текстом, весить будет гроши. то есть, сфинкс при ответе выдает, учитывая офсет и лимит записи в поиске, именно те поля которые ты указал в конфиге, типа ид прайс и тд, в данном случае еще и текст. лишнего он выдавать не должен, искать да, но не выдавать. Соответственно делаешь запрос к сфинксу, потом из его хитов вылавливаешь айдишники и цепляешь к ним запрос из бд.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 3
ThunderCat
@ThunderCat Куратор тега MySQL
{PHP, MySql, HTML, JS, CSS} developer
Если делать простой запрос LIKE '%%
начнем с того что это самый неправильный метод работы с текстом. То есть его используют только когда по другому уже совсем никак.
Во первых - какого рода тексты хранятся в записях? Длинна, тип поля.
Сильно подозреваю что фултекстсерч может резко поменять ситуацию.

UPD: https://habrahabr.ru/post/25646/#comment_641326 что как мы видим на несколько порядков быстрее.
Ответ написан
opium
@opium
Просто люблю качественно работать
Файл индекса слишком большой вы явно лишнего наиндексировали
Ответ написан
Это, конечно, не как бы ответ, но и не глумёж.
1. Яндекс, Гугл - выдают быстро поиск по гораздо большему массиву.
Но вряд ли они используют при этом Сфинкса.
2. Не думал, что напишу такое про ES, но
Похоже, он в вашем случае таки решит вопрос, если его правильно приготовить. Ибо в любом случае, при таких объёмах +/- 1-2-5 машины не выглядят излишеством.
Если не сложно, можете рассказать, почему "ES не подходит"?
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы