SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 24.09.2012 21:39:24

Doxtor
Завсегдатай
Зарегистрирован: 06.08.2009
Сообщений: 61

Оптимизация SELECT/UPDATE в цикле

Решение "в лоб" выглядит так:


$result = mysql_query("SELECT id FROM node", $db);
$myrow = mysql_fetch_array($result);

do{

$node_id = $myrow["id"];


$result_select_1 = mysql_query("SELECT ...WHERE ... id='$node_id'", $db);
$select_1 = mysql_fetch_array($result_select_1);
$rating = $select_1["rating"];


$result_select_2 = mysql_query("SELECT ...WHERE ... id='$node_id'", $db);
$select_2 = mysql_fetch_array($result_select_1);
$votes= $select_2["votes"];


$result_rating_votes = mysql_query("UPDATE node SET
                                                 rating = '$rating',
                                                 votes = '$votes'                                                
                                  WHERE id = '$node_id'"
, $db);

}
   while ($myrow =  mysql_fetch_array($result));  
 


Итого имеем два SELEKTa и один UPDATE  в цикле.
База растёт => время выполнения скрипта подходит к критическому уровню.

Объединить два SELEKTa нельзя, там нечего объединять.

Помогите пожалуйста советом.
Заранее спасибо.
С уважением.

Отредактированно Doxtor (24.09.2012 21:40:16)

Неактивен

 

#2 24.09.2012 22:09:25

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2422

Re: Оптимизация SELECT/UPDATE в цикле

Скорость выполнения запроса "SELECT id FROM node"  может немного ускорить наличие индекса на id, ну или если у id первичный ключ.

Если Вы приведете полностью текст запросов типа SELECT ...WHERE ... id='$node_id'", то можно подумать как их оптимизировать.

Запрос с update в теории можно было бы организовать так, чтобы не писать цикл, если, конечно можно на уровне SQL вычислить те значения, которые Вы вычисляете в цикле.
Но для этого нужно больше конкретики.


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#3 25.09.2012 11:39:43

Doxtor
Завсегдатай
Зарегистрирован: 06.08.2009
Сообщений: 61

Re: Оптимизация SELECT/UPDATE в цикле

Лично я предполагал, что внутри селектов всё "максимально" оптимизировано. Но давайте попробуем:


$result_select_1= mysql_query("SELECT
general_cnt.node_id,
general_cnt.general_id,
AVG(general_cnt.note)
FROM general_cnt
LEFT JOIN vote ON general_cnt.vote_id = vote.id
WHERE general_cnt.node_id='$node_id'
AND vote.vote_date > CURRENT_DATE() - INTERVAL 2 YEAR
LIMIT 1"
, $db);
$select_1 = mysql_fetch_array($result_select_1);
$rating = round($select_1["AVG(general_cnt.note)"],1);
 



$result_select_2 = mysql_query("SELECT
COUNT(vote.id) AS itogo_golosov,
vote.vote_date,
vote.node_id
FROM vote
WHERE vote.node_id='$node_id'  
AND vote.vote_date > CURRENT_DATE() - INTERVAL 2 YEAR"
, $db);
$select_2 = mysql_fetch_array($result_select_2);
$votes = $select_2['itogo_golosov'];
 


Распределение времени выполнения:
select_1 - 5 сек.
select_2 - 9 сек
update - 2 сек.

Спасибо.

Отредактированно Doxtor (25.09.2012 12:42:06)

Неактивен

 

#4 25.09.2012 14:00:30

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2422

Re: Оптимизация SELECT/UPDATE в цикле

Если еще не созданы, то я рекомендовал бы создать индексы на general_cnt.node_id и vote.vote_date. Ну и составной на поля (node_id,vote_date) в таблице vote.


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#5 25.09.2012 14:27:43

Doxtor
Завсегдатай
Зарегистрирован: 06.08.2009
Сообщений: 61

Re: Оптимизация SELECT/UPDATE в цикле

Индексы и первичные ключи есть.

vote.node_id не было индекса.
Добавил, ускорение в 16 раз.
Спасибо.

Хотелось бы, конечно, полностью избавиться от цикла.
Сейчас добью INNER JOIN и выложу решение (если сам справлюсь)

Отредактированно Doxtor (25.09.2012 15:09:02)

Неактивен

 

#6 25.09.2012 21:41:55

Doxtor
Завсегдатай
Зарегистрирован: 06.08.2009
Сообщений: 61

Re: Оптимизация SELECT/UPDATE в цикле

Полностью избавиться от циклов не получилось.
Результат: уменьшение времени запросов в 20 !!! раз.
Пока меня это устраивает. При увеличении времени буду смотреть в сторону временных таблиц.
Объединить два запроса в один не удалось из-за того, что в первом запросе:
LEFT JOIN vote ON general_cnt.vote_id = vote.id

а во втором:
INNER JOIN vote ON vote.node_id = node.id

Было ли какое-либо решение?


Решение выглядит так:

$result_select_1= mysql_query("SELECT  
general_cnt.node_id,
general_cnt.general_id,
AVG(general_cnt.note) AS srednee,
node.id
FROM node
INNER JOIN general_cnt ON general_cnt.node_id = node.id
LEFT JOIN vote ON general_cnt.vote_id = vote.id
WHERE vote.vote_date > CURRENT_DATE() - INTERVAL 2 YEAR
GROUP BY node.id"
],1);
do{

...UPDATE...srednee...

}
while

$result_select_2 = mysql_query("SELECT  
COUNT(vote.id) AS itogo_golosov,
vote.vote_date,
vote.node_id,
node.id
FROM node
INNER JOIN vote ON vote.node_id = node.id
WHERE vote.vote_date > CURRENT_DATE() - INTERVAL 2 YEAR
GROUP BY node.id"
, $db);
$select_2 = mysql_fetch_array($result_select_2);
$votes = $select_2['itogo_golosov'];

do{

...UPDATE...itogo_golosov

}
while



Время выполнения менее 0,8 секунды

Отредактированно Doxtor (25.09.2012 21:42:32)

Неактивен

 

#7 25.09.2012 21:44:41

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2422

Re: Оптимизация SELECT/UPDATE в цикле

Наверное Вы имели в виду не временные таблицы, а таблицы с движком memory.

Насчет циклов - не факт, что избавившись от цикла скорость увеличилась бы. Практика показывает, что несколько простых запросов работают быстрее, чем 1 навороченный.


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#8 25.09.2012 22:06:58

Doxtor
Завсегдатай
Зарегистрирован: 06.08.2009
Сообщений: 61

Re: Оптимизация SELECT/UPDATE в цикле

Имел в виду:
1. SELECT
2. CREATE TEMPORARY TABLE идентичной обновляемой
3. UPDATE через TEMPORARY TABLE (без цикла)

нет?

deadka написал:

Насчет циклов - не факт, что избавившись от цикла скорость увеличилась бы. Практика показывает, что несколько простых запросов работают быстрее, чем 1 навороченный.

Это да и возможно я сэкономил бы ещё пару миллисекунд (определить это "по-быстрому" не получилось)
Просто в моём случае "несколько" это 650 запросов, в перспективе 6,5 К, и поэтому я думал, что один сложный запрос может оказаться быстрее.

Отредактированно Doxtor (25.09.2012 22:07:16)

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson