Перейти из форума на сайт.

НовостиФайловые архивы
ПоискАктивные темыТоп лист
ПравилаКто в on-line?
Вход Забыли пароль? Первый раз на этом сайте? Регистрация
Компьютерный форум Ru.Board » Интернет » Web-программирование » Оптимизация запроса MySQL

Модерирует : Cheery

 Версия для печати • ПодписатьсяДобавить в закладки
Страницы: 1 2 3 4 5 6

Открыть новую тему     Написать ответ в эту тему

APTEM



Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

Цитата:
как правильно поступать - выбрать все данные и раскидать с помощью php, или все таки делать все  условия в самом мускуле ?

как правило, лучше доверить такую работу серверу БД: меньше траффика, меньше загрузка app-сервера. однако, БД не всегда знает, какими объёмами придётся оперировать: например в результате какого-то подзапроса должен получиться rowset из 2-3 строк, а БД посчитает, что будет несколько тысяч, и запрос будет выполняться по очень неоптимальному сценарию. именно в этом случае имеет смысл разделить задачу на несколько запросов и разрулить всё на app-сервере.

Всего записей: 396 | Зарегистр. 16-07-2004 | Отправлено: 18:49 25-01-2010
zerkms

Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору

Цитата:
например в результате какого-то подзапроса должен получиться rowset из 2-3 строк, а БД посчитает, что будет несколько тыся

БД не ошибается просто так. если запрос выполняется медленно - то или запрос кривой, или схема кривая, или (довольно редко) и вправду программист умнее оптимизатора субд.

----------
tvfёdor - оперативно уведомляет о раздачах rutracker | Блог об иммиграции в Новую Зеландию

Всего записей: 387 | Зарегистр. 07-05-2004 | Отправлено: 02:11 26-01-2010
kolyas



Junior Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
вопрос
 
объединение с доп условием как лучше использовать

Код:
 
Select  
*
FROM
kat_tv LEFT JOIN kat_model ON kat_tv.model_id= kat_model.id  AND kat_model.visible = 1  
 
 

 
или
 

Код:
 
Select
*
FROM
kat_tv LEFT JOIN kat_model ON kat_tv.model_id= kat_model.id
WHERE
kat_model.visible = 1  
 

 
 
Добавлено:
и еще .. что "тяжелее" для mysql подзапрос или JOIN ?

Всего записей: 137 | Зарегистр. 19-03-2007 | Отправлено: 15:37 29-01-2010
APTEM



Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору

Цитата:
объединение с доп условием как лучше использовать

логичнее первый вариант: он поясняет разработчику логику запроса. серверу БД абсолютно пофиг: он построит один и тот же план.

Цитата:
и еще .. что "тяжелее" для mysql подзапрос или JOIN ?

как правило, подзапрос тяжелее. особенно, если подзапрос с условием, зависящим от значения поля текущей записи. это вообще ж.па для БД. в таких случаях лучше сделать один группирующий подзапрос. если же подзапрос для каждой записи должен дать один и тот же rowset, такой подзапрос можно смело использовать. А вообще, всё зависит от количества записей в связанных таблицах.
 
три разных запроса, дающих один и тот же результат:

Код:
SELECT u.id, count(p.id) cnt FROM users u
  INNER JOIN posts p ON p.user_id=u.id
  GROUP BY u.id


Код:
SELECT u.id, (SELECT count(p.id) FROM posts p WHERE p.user_id=u.id) cnt FROM users u


Код:
SELECT u.id, p.cnt FROM users u
  INNER JOIN (SELECT user_id, count(id) cnt FROM posts GROUP BY user_id) p ON p.user_id=u.id

план выполнения на трёх юзерах и шести постах дал следующие времена исполнения: 22%, 21%, 57%. Однако, на другом количестве записей результат может сильно отличаться

Всего записей: 396 | Зарегистр. 16-07-2004 | Отправлено: 23:11 29-01-2010
zerkms

Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору

Цитата:
 
логичнее первый вариант: он поясняет разработчику логику запроса. серверу БД абсолютно пофиг: он построит один и тот же план.  

неправда. планы будут разные (ибо LEFT JOIN)
во втором запросе, благодаря зависимости от kat, LEFT легко можно заменить на INNER и ничего не изменится.
в первом же запросе, как и ожидается, правая половина будет добита NULL'ами, если условие объединения не выполнится.

----------
tvfёdor - оперативно уведомляет о раздачах rutracker | Блог об иммиграции в Новую Зеландию

Всего записей: 387 | Зарегистр. 07-05-2004 | Отправлено: 16:12 30-01-2010
kolyas



Junior Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
APTEM
zerkms
 
INNER легче LEFT ?
 
у меня в базе, данные могут отсуствовать и подменяться NULL'ями только в одном месте, может есть тогда смысл убрать везде LEFT ?

Всего записей: 137 | Зарегистр. 19-03-2007 | Отправлено: 14:42 31-01-2010
zerkms

Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
kolyas
INNER легче, чем LEFT
но они делают разную работу - сам понимаешь. если нужно обычное пересечение множеств - тогда INNER. иначе - LEFT.

----------
tvfёdor - оперативно уведомляет о раздачах rutracker | Блог об иммиграции в Новую Зеландию

Всего записей: 387 | Зарегистр. 07-05-2004 | Отправлено: 17:21 31-01-2010
rtyug



Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
а если вместо INNER сравнить по id  
 
WHERE t1.id = t2.id
 
?
 

Всего записей: 490 | Зарегистр. 13-05-2009 | Отправлено: 17:36 31-01-2010
kolyas



Junior Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
zerkms
 
вернусь к запросам из поста выше
если их переделать вот так.. как я понял, они станут полностью одинаковыми, так как серер БД все равно все условия сам выкидывает в WHERE ?
 

Код:
Select  
*  
FROM  
kat_tv INNER JOIN kat_model ON kat_tv.model_id= kat_model.id  AND kat_model.visible = 1  
 

 
=
 

Код:
Select  
*  
FROM  
kat_tv INNER JOIN kat_model ON kat_tv.model_id= kat_model.id  
WHERE
kat_model.visible = 1  
 

 
 
Добавлено:
с LEFT | RIGHT  разобрался ..  спасибо
 
Добавлено:
Как нужно изменить запрос,  так чтобы выбиралось по 4 строки из таблицы SV для каждого TV

Код:
 
SELECT
    tv.id,
    tv.name,
    kat.name,
    sv.name
FROM
    tv    INNER JOIN tv_kat ON tv.id = tv_kat.tv_id
        INNER JOIN kat ON kat.id=tv_kat.kat_id
        INNER JOIN kat_sv ON kat.id=kat_sv.kat_id
        INNER JOIN sv ON sv.id=kat_sv.sv_id
 

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

Всего записей: 137 | Зарегистр. 19-03-2007 | Отправлено: 17:42 31-01-2010 | Исправлено: kolyas, 21:11 31-01-2010
zerkms

Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
kolyas
нет, запросы !=
 
по выборке они одинаковые, но оптимизироваться будут по-разному (если, конечно оптимизатор не настолько гениальный, чтобы самому упростить, в чём я очень сомневаюсь)
первый вариант должен быть быстрее второго. вообще не вижу смысла часть условия объединения переносить во WHERE, где ему банально не место.
 
Добавлено:

Цитата:
так чтобы выбиралось по 4 строки из таблицы SV для каждого TV  

завести переменную
SET @I:=0;
 
в запросе её увеличивать:
SELECT ..., @I:=@I+1
 
группировать по tv + остатку от деления I на 4:
GROUP BY `tv`.`id`, @I % 4
 
но вообще этот запрос очень медленный, и за такой запрос я бы подчинённым руки оторвал

----------
tvfёdor - оперативно уведомляет о раздачах rutracker | Блог об иммиграции в Новую Зеландию

Всего записей: 387 | Зарегистр. 07-05-2004 | Отправлено: 01:23 01-02-2010
kolyas



Junior Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
zerkms
получается все таки проще оставить как есть, перекинув в массив php, а там уже как обычно играться как угодно.. ?
 
как все таки все не просто
 
Добавлено:
и снова я и с нова с запросом =))
может быть для кого-то это очевидное, для меня пока это почти дремучий лес..  
 
 
к категориям добавились parent_id
 
 
 
нужно вытащить только tv которые попадают в  
 
kat.name="группа1" (включая дочерние, их может быть несколько)
 

Код:
 
Select
    tv.id
    tv.name
FROM
    tv    INNER JOIN tv_kat ON tv_kat.tv_id = tv.id
        INNER JOIN kat ON kat.id= tv_kat.kat_id
        AND (kat.name="Группа1" OR kat.parent_id=(SELECT id FROM kat WHERE parent_id=(SELECT id FROM kat WHERE name="Группа1")))
 
 

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

Всего записей: 137 | Зарегистр. 19-03-2007 | Отправлено: 07:41 01-02-2010
zerkms

Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
никак. выгреби отдельным запросом нужные id и тут их добавь через IN ()

----------
tvfёdor - оперативно уведомляет о раздачах rutracker | Блог об иммиграции в Новую Зеландию

Всего записей: 387 | Зарегистр. 07-05-2004 | Отправлено: 09:20 01-02-2010
kolyas



Junior Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
как оптимальнее можно получить из таблицы kat (рисунок выше) на выходе вот это:
 
ID
NAME (где parent_id=0)
 
count (количество дочерних id для ID, где parent_id= ID )
 
 
 
Добавлено:
 
вроде сам написал..
и даже работает..
 
это оптимальный вариант ?  

Код:
 
SELECT *, (@aa:=id)  , (SELECT count(*) FROM kat WHERE parent_id= @aa) as count_kat  FROM kat WHERE parent_id=0

 
Добавлено:
и как можно чтобы не получалось дополнительное поле (@aa:=id)

Всего записей: 137 | Зарегистр. 19-03-2007 | Отправлено: 16:56 04-02-2010 | Исправлено: kolyas, 18:31 04-02-2010
kolyas



Junior Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
видимо ответа не будет =(

Всего записей: 137 | Зарегистр. 19-03-2007 | Отправлено: 02:50 08-02-2010
zerkms

Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
kolyas
потому что не совсем понятно, чем ты там занимаешься.

----------
tvfёdor - оперативно уведомляет о раздачах rutracker | Блог об иммиграции в Новую Зеландию

Всего записей: 387 | Зарегистр. 07-05-2004 | Отправлено: 04:07 08-02-2010
kolyas



Junior Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
zerkms
..пишу простой каталог с нуля.. существующие не очень нравится..
 
по пути улучшаю знания основ sql .. вернее как строить запросы не допуская ошибок на старте..  
 
p.s. благодаря вашим постам стал использовать сначала INNER JOIN и LEFT JOIN вместо подзапросов..  
скорость выборки ускорилась примерно в 2 раза в моей маленькой базе, а => при проектировании большой базы я выиграю больше время и ресурсов ..
 
..так что огромное спасибо за ответы..  zerkms
 
 
и я думаю стоило бы эту ветку закрепить и продолжать.. думаю тут поучиться есть кому и у кого..  
 
 
p.p.s. по поводу прошлого запроса ..  я его оставил, так как есть, думаю для моей задачи он оптимален..

Всего записей: 137 | Зарегистр. 19-03-2007 | Отправлено: 18:50 08-02-2010
onwars

Newbie
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
как упростить этот код до минимума запросов?
 

Код:
 
$q2 = mysql_query("select `name_team`  from `m_start` where `chemp`='".$k['name']."' LIMIT 16; ");  
while( $x2 = mysql_fetch_row($q2))  
{ $w2[] = $x2[0]  ; }  
shuffle($w2);  
//////////////  
$q = mysql_result(mysql_query("select `id` from `m_team` where `name`='".$w2[0]."'"),0);  
$q1 = mysql_result(mysql_query("select `id` from `m_team` where `name`='".$w2[1]."'"),0);  
$q2 = mysql_result(mysql_query("select `id` from `m_team` where `name`='".$w2[2]."'"),0);  
$q3 = mysql_result(mysql_query("select `id` from `m_team` where `name`='".$w2[3]."'"),0);  
 
 
////////////  
mysql_query("INSERT INTO `m_cl` set `time`='".$realtime."', `tur`='1', `chemp`='".$k['name']."',`id_team1`='".$q."',`name_team1`='".$w2[0]."',`id_team2`='".$q1."',`name_team2`='".$w2[1]."' ;");  
mysql_query("INSERT INTO `m_cl` set `time`='".$realtime."', `tur`='1', `chemp`='".$k['name']."',`id_team1`='".$q2."',`name_team1`='".$w2[2]."',`id_team2`='".$q3."',`name_team2`='".$w2[3]."' ;");
 

Всего записей: 19 | Зарегистр. 10-04-2010 | Отправлено: 03:13 11-04-2010
2007GhOsT2007

Newbie
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Ну тут все зависит от того, какая цель этого куска кода... Кстати, а вот в первом запросе стоит ограничение на 16 записей, потом полученный массив перемешивается, а потом делаем 4 запроса на первые 4 записи. Это весь кусок кода и там будет действительно только 4 записи или код не полный? Вообщем, в случае если, если я верно все понял, должен нормально работать следующий код:

Код:
    $a = null;
    $rows = mysql_query('SELECT `m_team`.`id` AS `tid`, `m_team`.`name` AS `tname` FROM `m_start` LEFT JOIN `m_team` ON (`m_team`.`name` = `m_start`.`name_team`) WHERE `m_start`.`chemp` = \'' . $k['name'] . '\' LIMIT 16');
    while ($row = mysql_fetch_array($rows))
    {
        $a[] = array($row['tid'], $row['tname']);
    }
     
    $a = array_rand($a, 4);
     
    $first = true;
    foreach($a as &$item)
    {
        if ($first)
        {
            $f_id = $item[0];
            $f_name = $item[1];
            $first = false;
        }
        else
        {
            mysql_query('INSERT INTO `m_cl` set  
                `time` = \'' . $realtime . '\',  
                `tur`=\'1\',  
                `chemp`=\'' . $k['name'] . '\',  
                `id_team1` = \'' . $f_id . '\',  
                `name_team1` = \'' . $f_name . '\',  
                `id_team2` = \'' . $item[0] . '\',  
                `name_team2` = \'' . $item[1] . '\'
            ;');  
             
            $f_id = null;
            $f_name = null;
             
            $first = true;
        }
    }

Всего записей: 26 | Зарегистр. 13-02-2007 | Отправлено: 02:37 12-04-2010 | Исправлено: 2007GhOsT2007, 02:48 12-04-2010
onwars

Newbie
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
вот весь код. Он служит для  отбора 16 команд и создания матчей первого тура на 8игр.

Код:
 
$q2 = mysql_query("select `name_team`  from `m_start` where `chemp`='".$k['name']."' LIMIT 16; ");
while( $x2 = mysql_fetch_row($q2))
{ $w2[] = $x2[0]  ; }
shuffle($w2);
//////////////
$q = mysql_result(mysql_query("select `id` from `m_team` where `name`='".$w2[0]."'"),0);
$q1 = mysql_result(mysql_query("select `id` from `m_team` where `name`='".$w2[1]."'"),0);
$q2 = mysql_result(mysql_query("select `id` from `m_team` where `name`='".$w2[2]."'"),0);
$q3 = mysql_result(mysql_query("select `id` from `m_team` where `name`='".$w2[3]."'"),0);
$q4 = mysql_result(mysql_query("select `id` from `m_team` where `name`='".$w2[4]."'"),0);
$q5 = mysql_result(mysql_query("select `id` from `m_team` where `name`='".$w2[5]."'"),0);
$q6 = mysql_result(mysql_query("select `id` from `m_team` where `name`='".$w2[6]."'"),0);
$q7 = mysql_result(mysql_query("select `id` from `m_team` where `name`='".$w2[7]."'"),0);
$q8 = mysql_result(mysql_query("select `id` from `m_team` where `name`='".$w2[8]."'"),0);
$q9 = mysql_result(mysql_query("select `id` from `m_team` where `name`='".$w2[9]."'"),0);
$q10 = mysql_result(mysql_query("select `id` from `m_team` where `name`='".$w2[10]."'"),0);
$q11 = mysql_result(mysql_query("select `id` from `m_team` where `name`='".$w2[11]."'"),0);
$q12 = mysql_result(mysql_query("select `id` from `m_team` where `name`='".$w2[12]."'"),0);
$q13 = mysql_result(mysql_query("select `id` from `m_team` where `name`='".$w2[13]."'"),0);
$q14 = mysql_result(mysql_query("select `id` from `m_team` where `name`='".$w2[14]."'"),0);
$q15 = mysql_result(mysql_query("select `id` from `m_team` where `name`='".$w2[15]."'"),0);
 
 
////////////
mysql_query("INSERT INTO `m_cl` set `time`='".$realtime."', `tur`='1', `chemp`='".$k['name']."',`id_team1`='".$q."',`name_team1`='".$w2[0]."',`id_team2`='".$q1."',`name_team2`='".$w2[1]."' ;");
mysql_query("INSERT INTO `m_cl` set `time`='".$realtime."', `tur`='1', `chemp`='".$k['name']."',`id_team1`='".$q2."',`name_team1`='".$w2[2]."',`id_team2`='".$q3."',`name_team2`='".$w2[3]."' ;");
mysql_query("INSERT INTO `m_cl` set `time`='".$realtime."', `tur`='1', `chemp`='".$k['name']."',`id_team1`='".$q4."',`name_team1`='".$w2[4]."',`id_team2`='".$q5."',`name_team2`='".$w2[5]."' ;");
mysql_query("INSERT INTO `m_cl` set `time`='".$realtime."', `tur`='1', `chemp`='".$k['name']."',`id_team1`='".$q6."',`name_team1`='".$w2[6]."',`id_team2`='".$q7."',`name_team2`='".$w2[7]."' ;");
mysql_query("INSERT INTO `m_cl` set `time`='".$realtime."', `tur`='1', `chemp`='".$k['name']."',`id_team1`='".$q8."',`name_team1`='".$w2[8]."',`id_team2`='".$q9."',`name_team2`='".$w2[9]."' ;");
mysql_query("INSERT INTO `m_cl` set `time`='".$realtime."', `tur`='1', `chemp`='".$k['name']."',`id_team1`='".$q10."',`name_team1`='".$w2[10]."',`id_team2`='".$q11."',`name_team2`='".$w2[11]."' ;");
mysql_query("INSERT INTO `m_cl` set `time`='".$realtime."', `tur`='1', `chemp`='".$k['name']."',`id_team1`='".$q12."',`name_team1`='".$w2[12]."',`id_team2`='".$q13."',`name_team2`='".$w2[13]."' ;");
mysql_query("INSERT INTO `m_cl` set `time`='".$realtime."', `tur`='1', `chemp`='".$k['name']."',`id_team1`='".$q14."',`name_team1`='".$w2[14]."',`id_team2`='".$q15."',`name_team2`='".$w2[15]."' ;");
 

Всего записей: 19 | Зарегистр. 10-04-2010 | Отправлено: 20:08 13-04-2010
Delta RuBoard



Member
Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору
onwars
попробуй вот так
 

Код:
<?    
$q2 = mysql_query("    
    SELECT    
        m_start.name_team,
        m_team.id
    FROM  
        m_start,
        m_team
    WHERE  
        m_start.chemp = '".$k['name']."'  AND
        m_start.name_team = m_team.name
    LIMIT 16;  
");
$i = 0;
while( $x2 = mysql_fetch_assoc($q2))  
{  
    $w2[$i]['name_team'] = $x2['name_team']  ;  
    $w2[$i]['id'] = $x2['id']  ;  
    $i++;
}
$i = 0;
while ($i < 16)
{
    mysql_query("INSERT INTO `m_cl` set `time`='".$realtime."', `tur`='1', `chemp`='".$k['name']."',`id_team1`='".$w2[$i]['id']."',`name_team1`='".$w2[$i]['name_team']."',`id_team2`='".$q1."',`name_team2`='".$w2[($i+1)]['name_team']."' ;");  
    $i++;
}
?>


----------
мой маленький блог
Создание on-line игр

Всего записей: 382 | Зарегистр. 21-06-2005 | Отправлено: 05:40 14-04-2010 | Исправлено: Delta RuBoard, 05:41 14-04-2010
Открыть новую тему     Написать ответ в эту тему

Страницы: 1 2 3 4 5 6

Компьютерный форум Ru.Board » Интернет » Web-программирование » Оптимизация запроса MySQL


Реклама на форуме Ru.Board.

Powered by Ikonboard "v2.1.7b" © 2000 Ikonboard.com
Modified by Ru.B0ard
© Ru.B0ard 2000-2025

LiteCoin: LgY72v35StJhV2xbt8CpxbQ9gFY6jwZ67r

Рейтинг.ru