Оптимизация запроса в БД. В цикле.

F
На сайте с 06.02.2012
Offline
101
853

Здравствуйте.

На странице имеется массив $arr, небольшой, не более пяти элементов.

Надо проверить каждый элемент на совпадение в поле description таблицы БД и вывести результаты, если совпадения найдены.

Совпадение частичное, типа "SELECT * FROM table WHERE description LIKE '%bla-bla%' "

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

Как я понимаю, если бы искать точное сопадение, подошёл бы оператор IN(), чтобы одним запросом проверить все элементы массива.

Не пробовал, но должно работать по идее "SELECT * FROM table WHERE description IN($arr) ", если не напутал с кавычками...

А как быть с частичным совпадением?

Можно ли как то объединять операторы IN и LIKE %%

Aisamiery
На сайте с 12.04.2015
Offline
217
#1

WHERE `desc` LIKE '%param1%' OR `desc` LIKE '%param2%' OR `desc` LIKE '%param3%' ...

В один запрос. Табличка то одна. Когда ваша табличка попадет в оперативку, гонять по ней операторы уже нормально, отдельными запросами вы увеличиваете немного другие вещи.

Надо запомнить, что все операции можно переложить на БД и в 90% случаев она это сделает быстрее, чем вы на php

Разработка проектов на Symfony, Laravel, 1C-Bitrix, UMI.CMS, OctoberCMS
F
На сайте с 06.02.2012
Offline
101
#2

А как же потом разделять?

В качестве param1, param2 будут элементы массива и каждому должен соответствовать свой desc

А потом в тексте происходит подмена элементов массива ссылками на файл.

У меня сейчас так работает:

foreach($arr_ic as $ic0)
{
$ic0=$mysqli->real_escape_string($ic0);
$resultz=$mysqli->query('SELECT name,desc,text FROM table WHERE desc LIKE "%'.$ic0.'%"');
$ro=$resultz->num_rows;
if($ro>0) {
$dat=$resultz->fetch_assoc();
$name=$dat['name'];$desc=$dat['desc']; $titl=$dat['text'];
$ic1=' <a title="'.$desc.' - '.$titl.'" href="/'.$name.'.rar">'.$ic0.'</a>';
$IC_text=str_replace($ic0,$ic1,$IC_text);
}
}

Работает нормально, но хотелось бы запрос отдельно от цикла...

Aisamiery
На сайте с 12.04.2015
Offline
217
#3
fordzon:

Работает нормально, но хотелось бы запрос отдельно от цикла...

Как только перестанет работать, начнете думать. Если все сделать по феншую, то во-первых, пройдет 100 лет, во-вторых, ничего не будет работать. Оптимизировать нужно там, где тормозит, а не там где кто то на форуме написал.

LEOnidUKG
На сайте с 25.11.2006
Online
1600
#4

Вместо %LIKE% вам лучше сделать FULLTEXT на столбец и поиск делать через MATCH … AGAINST. В разы быстрее будет.

А цикл оставляйте, если он нужен.

✅ Трастовых площадок под размещение статей и ссылок. Опыт 14 лет! ( https://searchengines.guru/ru/forum/675690 ) ⭐ Купить вечные трастовые ссылки для сайта ( https://getmanylinks.ru/?srh ) ⭐ Ускорение ваших сайтов (WP, Opencart и др.) + Настройка сервера ( https://searchengines.guru/ru/forum/997205 )
F
На сайте с 06.02.2012
Offline
101
#5

Индексами ещё не пользовался... пробую...

FULLTEXT на столбец.... Не получается... phpMyAdmin пишет ошибку #1170 - BLOB/TEXT column 'text' used in key specification without a key length

LEOnidUKG
На сайте с 25.11.2006
Online
1600
#6

Надо размер максимальный задать для столбца.

F
На сайте с 06.02.2012
Offline
101
#7

Тип поля выставлен text. Длина/значения - пусто. Что туда вписать?

---------- Добавлено 16.02.2017 в 17:20 ----------

как я понял запрос должен выглядеть примерно так:

SELECT name,desc,text FROM table WHERE MATCH(desc) AGAINST('.$ic0.')

LEOnidUKG
На сайте с 25.11.2006
Online
1600
#8
Что туда вписать?

Определить сколько символов у вас используется в этом столбце и вписать с запасом число. Потом проставить полный индекс.

примерно так:

Да.

F
На сайте с 06.02.2012
Offline
101
#9

ОК.

Индекс FULLTEXT встал.

Теперь попробую поменять запрос.

---------- Добавлено 16.02.2017 в 17:50 ----------

Работает. По скорости так сходу не могу судить... Верю на слово, ибо сам с индексами никогда не работал.. слышал лишь что существенно ускоряется поиск в таблице.

Тип столбца поменял на varchar(255), мне там длины хватит.

Спасибо, парни, за помощь!

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий