За последние 24 часа нас посетили 38562 программиста и 1284 робота. Сейчас ищут 1055 программистов ...

2 запроса > 1?

Тема в разделе "MySQL", создана пользователем Freakmeister, 19 сен 2011.

  1. Freakmeister

    Freakmeister Активный пользователь

    С нами с:
    20 дек 2009
    Сообщения:
    888
    Симпатии:
    5
    Допиливал статистику игрового сервера: http://109.86.199.237/stats/
    На главной странице я добавил внизу блок "Суперзвёзды сервера", в итоге страница стала заметно дольше грузиться. Каждая строчка этого блока это 1-2 отдельных запросов в БД. Код целиком здесь приводить не буду, ибо многабукаф, но сами запросы вот они:

    PHP:
    1. <?php
    2.     //Покрыл наибольшее расстояние
    3.     $query = mysql_query("SELECT uuid, player_name, distance_traveled FROM `players` ORDER BY distance_traveled DESC LIMIT 1");
    4.     $row = mysql_fetch_array($query);
    5.  
    6.  
    7.     //Поставил больше всех блоков
    8.     $query = mysql_query("SELECT uuid FROM `blocks` GROUP BY uuid");
    9.     while ($row = mysql_fetch_array($query)) {
    10.         $players[]=$row['uuid'];
    11.     }
    12. foreach ($players as $uid) {
    13.     $row = mysql_fetch_assoc(mysql_query("SELECT SUM(num_placed) AS placedTotal FROM blocks WHERE uuid = '$uid'"));
    14.     $blocks_placed[$uid]=$row['placedTotal'];
    15. }
    16.  
    17.  
    18.     //Уничтожил больше всех блоков
    19.     $query = mysql_query("SELECT uuid FROM `blocks` GROUP BY uuid");
    20.     while ($row = mysql_fetch_array($query)) {
    21.         $players[]=$row['uuid'];
    22.     }
    23. foreach ($players as $uid) {
    24.     $row = mysql_fetch_assoc(mysql_query("SELECT SUM(num_destroyed) AS destroyedTotal FROM blocks WHERE uuid = '$uid'"));
    25.     $blocks_destroyed[$uid]=$row['destroyedTotal'];
    26. }
    27.  
    28.  
    29.     //Самый опасный убийца мобов
    30. $query = mysql_query("SELECT killed_by_uuid FROM `kills` GROUP BY killed_by_uuid");
    31.     while ($row = mysql_fetch_array($query)) {
    32.         if ($row['killed_by_uuid']) {
    33.            $players[]=$row['killed_by_uuid'];
    34.         }
    35.     }
    36.  
    37. foreach ($players as $uid) {
    38.     $k12 = mysql_fetch_array(mysql_query("SELECT COUNT(*) FROM `kills` WHERE killed_by_uuid ='$uid'"));
    39.     $kills[$uid] = $k12[0];
    40. }
    41.  
    42.  
    43.     //Умер наибольшее количество раз
    44. $query = mysql_query("SELECT killed_uuid FROM `kills` GROUP BY killed_uuid");
    45.     while ($row = mysql_fetch_array($query)) {
    46.         if ($row['killed_uuid']) {
    47.            $players[]=$row['killed_uuid'];
    48.         }
    49.     }
    50.  
    51. foreach ($players as $uid) {
    52.     $k12 = mysql_fetch_array(mysql_query("SELECT COUNT(*) FROM `kills` WHERE killed_uuid ='$uid'"));
    53.     $deaths[$uid] = $k12[0];
    54. }
    55.  
    56.  
    57.     //Самый активный игрок
    58.     $query = mysql_query("SELECT uuid, player_name, num_secs_loggedon FROM `players` ORDER BY num_secs_loggedon DESC");
    59.     $row = mysql_fetch_array($query);
    60. ?>
    Так вот, у меня вопрос - влияет ли вообще количество запросов на производительность, или тут всё зависит только от объёма выкаченной из БД информации? И если влияет, то реально ли объединить все эти запросы в 2-3?
     
  2. krow7

    krow7 Активный пользователь

    С нами с:
    12 авг 2009
    Сообщения:
    398
    Симпатии:
    0
    Адрес:
    из Азии
    Freakmeister
    а вы проверьте microtime'ом, какое кол-во времени уходит на запросы.
     
  3. alexfer

    alexfer Активный пользователь

    С нами с:
    2 авг 2010
    Сообщения:
    239
    Симпатии:
    0
    Может все таки лучше
    Код (Text):
    1. WHERE killed_uuid IN ()
    ?
     
  4. karakh

    karakh Активный пользователь

    С нами с:
    11 дек 2007
    Сообщения:
    1.344
    Симпатии:
    0
    в 12, 23, 37 и 51 строках надо не делать запрос в цикле, а в цикле собрать список uids и выбирать из базы одним запросом. Это уже может неплохо помочь
     
  5. Freakmeister

    Freakmeister Активный пользователь

    С нами с:
    20 дек 2009
    Сообщения:
    888
    Симпатии:
    5
    А в IN можно вставлять массив? Или массив сначала нужно склеивать в строку через implode?
     
  6. tommyangelo

    tommyangelo Старожил

    С нами с:
    6 дек 2009
    Сообщения:
    2.549
    Симпатии:
    0
    Адрес:
    Мариуполь
    Freakmeister
    Склеить через implode
     
  7. mrvalter

    mrvalter Активный пользователь

    С нами с:
    23 сен 2011
    Сообщения:
    3
    Симпатии:
    0
    //Поставил больше всех блоков
    $query = mysql_query("SELECT uuid FROM `blocks` GROUP BY uuid");
    while ($row = mysql_fetch_array($query)) {
    $players[]=$row['uuid'];
    }
    foreach ($players as $uid) {
    $row = mysql_fetch_assoc(mysql_query("SELECT SUM(num_placed) AS placedTotal FROM blocks WHERE uuid = '$uid'"));
    $blocks_placed[$uid]=$row['placedTotal'];
    }

    Тут я бы просто написал 1 запрос:

    SELECT distinct b.uuid, (SELECT SUM(num_placed) FROM blocks WHERE uuid = b.uuid) as placedTotal
    FROM `blocks` b
    ORDER BY placedTotal DESK
    LIMIT 1

    Соответственно и для других блоков так же по запросу. Так как в основном время тратится на установку соединения к БД и лучше записать один большой запрос чем десятки маленьких.

    Потом увидел 2 одинаковых запроса "SELECT uuid FROM `blocks` GROUP BY uuid" Нафига? Если один раз уже был. Можно использовать уже сконструированную переменную.

    Либо что бы вообще не заморачиваться пишем все в одном запросе:

    SELECT b.uuid,
    (SELECT count(*) FROM `blocks` where uuid=b.uuid) as count,
    (SELECT SUM(num_placed) FROM `blocks` where uuid=b.uuid) as placedTotal
    FROM `blocks` b
    GROUP by uuid
    ORDER BY count DESC, placedTotal DESC
    LIMIT 2

    Здесь первая позиция будет максимальное количество, вторая позиция максимальная сумма.
    только нужно будет сравнить максимальную сумму 2 позиции с 1 позицией. Возможно что 1 будет больше.
     
  8. Freakmeister

    Freakmeister Активный пользователь

    С нами с:
    20 дек 2009
    Сообщения:
    888
    Симпатии:
    5
    Короче, сделал так. Работать стало заметно быстрее, я прямо таки горжусь собой. 8)) Но нет предела совершенству. Можно ли сделать ещё меньше запросов?

    PHP:
    1. <?php
    2.  
    3. //Покрыл наибольшее расстояние
    4. $query = mysql_query("SELECT uuid, player_name, distance_traveled FROM `players` ORDER BY distance_traveled DESC LIMIT 1");
    5. $row = mysql_fetch_array($query);
    6.  
    7. $distance[0]=$row['uuid'];
    8. $distance[1]=$row['player_name'];
    9. $distance[2]=QueryUtils::formatDistance($row['distance_traveled']);
    10.  
    11. //Поставил больше всех блоков
    12. $row = mysql_fetch_assoc(mysql_query("SELECT SUM(num_placed) AS placedTotal, uuid FROM `blocks` GROUP BY uuid ORDER BY placedTotal DESC LIMIT 1"));
    13.  
    14. $_player = $serverObj->getPlayer($row['uuid']);
    15. $placed[0]=$row['uuid'];
    16. $placed[1]=$_player->getName();
    17. $placed[2]=$row['placedTotal'];
    18. unset($blocks);
    19.  
    20. //Уничтожил больше всех блоков
    21. $row = mysql_fetch_assoc(mysql_query("SELECT SUM(num_destroyed) AS destroyedTotal, uuid FROM `blocks` GROUP BY uuid ORDER BY destroyedTotal DESC LIMIT 1"));
    22. $_player = $serverObj->getPlayer($row['uuid']);
    23. $destroyed[0]=$row['uuid'];
    24. $destroyed[1]=$_player->getName();
    25. $destroyed[2]=$row['destroyedTotal'];
    26.  
    27. //Самый опасный убийца мобов
    28. $query = mysql_query("SELECT COUNT(killed_by_uuid) AS killsTotal, killed_by_uuid FROM `kills` GROUP BY killed_by_uuid ORDER BY killsTotal DESC LIMIT 2");
    29. $row = mysql_fetch_array($query);
    30. if (!$row['killed_by_uuid']) { $row = mysql_fetch_array($query); } //предохранитель на случай, если пустых записей больше всего
    31. $_player = $serverObj->getPlayer($row['killed_by_uuid']);
    32. $killer[0]=$row['killed_by_uuid'];
    33. $killer[1]=$_player->getName();
    34. $killer[2]=$row['killsTotal'];
    35.  
    36. //Умер наибольшее количество раз
    37. $query = mysql_query("SELECT COUNT(killed_uuid) AS killedTotal, killed_uuid FROM `kills` GROUP BY killed_uuid ORDER BY killedTotal DESC LIMIT 2");
    38. $row = mysql_fetch_array($query);
    39. if (!$row['killed_uuid']) { $row = mysql_fetch_array($query); } //предохранитель на случай, если пустых записей больше всего
    40. $_player = $serverObj->getPlayer($row['killed_uuid']);
    41. $killed[0]=$row['killed_uuid'];
    42. $killed[1]=$_player->getName();
    43. $killed[2]=$row['killedTotal'];
    44.  
    45. //Самый активный игрок
    46. $query = mysql_query("SELECT uuid, player_name, num_secs_loggedon FROM `players` ORDER BY num_secs_loggedon DESC");
    47.     $row = mysql_fetch_array($query);
    48. $active[0]=$row['uuid'];
    49. $active[1]=$row['player_name'];
    50. $active[2]=QueryUtils::formatSecs($row['num_secs_loggedon']);
    51.  
    52. ?>
     
  9. Luge

    Luge Старожил

    С нами с:
    2 фев 2007
    Сообщения:
    4.680
    Симпатии:
    1
    Адрес:
    Минск
    сделать сводную таблицу результатов и обновлять её по крону

    з.ы. да, я некропостер ;)