За последние 24 часа нас посетили 43030 программистов и 1268 роботов. Сейчас ищут 938 программистов ...

Вопрос по поводу оптимизации

Тема в разделе "Сделайте за меня", создана пользователем thezolotoi, 3 апр 2024.

Метки:
  1. thezolotoi

    thezolotoi Новичок

    С нами с:
    3 апр 2024
    Сообщения:
    1
    Симпатии:
    0
    Здравствуйте, как можно оптимизировать данный код (ускорить его выполнение)
    Короткая информация по коду:

    pdo - Это бд сайта
    $pdo2 - Это бд сервера
    $limit_man ->Кол-во людей которое мне нужно

    Сам код рабочий, использует запросы pdo (слегка изменёные создателем движка)

    Сам код:
    PHP:
    1.         $top_users = [];
    2.         $STH2 = $this->pdo->query("SELECT * FROM users WHERE gender = 1");
    3.         $STH2->setFetchMode(PDO::FETCH_OBJ);
    4.  
    5.         while ($row = $STH2->fetch()) {
    6.  
    7.  
    8.             $STH3 = $pdo2->prepare("SELECT * FROM `lvl_atm` WHERE steam = :_steam_id");
    9.             $STH3->execute(array(':_steam_id' => $row->steam_id));
    10.             $STH3->setFetchMode(PDO::FETCH_OBJ);
    11.             $user = $STH3->fetch();
    12.  
    13.             if ($user) {
    14.  
    15.                 $top_users[] = [
    16.                     'id' => $user->id,
    17.                     'nick' => $user->name,
    18.                     'kills' => $user->value,
    19.                     'steam' => $row->steam_id
    20.                 ];
    21.             }
    22.         }
    23.  
    24.         usort($top_users, function ($a, $b) {
    25.             return $b['kills'] - $a['kills'];
    26.         });
    27.         $top_three_users = array_slice($top_users, 0, $limit_man);  
    28.         foreach ($top_three_users as $user) {
    29.             $sort[] = $user['steam'];
    30.         }
    Логика работы или-же объяснение самого кода:
    Я сначала ищю всех пользователей на сайте кто выбрал определённый "гендер" на сайте,
    Потом перебираю данные из 2 бд (сервера) ищю данных игроков, добавляю в array массив $top_users
    И потом уже сортирую по "очкам", проблема в том что данных в таблице бд более 800-1к записей из-за чего код выполняеться мягко скажем медленно, интересуют идеи, замечания или-же готовое решение (если можно) по оптимизации кода.

    Сразу говорю нет возможности хранить все данные на 1 бд (из-за путаницы).Любые идеи\решения или-же критика с объяснениями одобряются.
     
  2. Bernardeschi

    Bernardeschi Новичок

    С нами с:
    9 дек 2022
    Сообщения:
    1
    Симпатии:
    0
    У вас на каждую итерацию идёт запрос в БД, что очень дорого обходиться, вам нужно сформировать строку из '_steam_id' и сделать один запрос типа 'SELECT * FROM `level_atm` WHERE steam in(' . $ваша строка . ')'
    P.S. Строка должна быть такого формата '1, 2, 3, 4, 5'
     
  3. ADSoft

    ADSoft Старожил

    С нами с:
    12 мар 2007
    Сообщения:
    3.866
    Симпатии:
    753
    Адрес:
    Татарстан
    медленно - потому что запросы в цикле - аццкое зло....

    советую логику переделать так:
    1. Запрос нужных пользователей из 1 бд
    2. формируем массив/строку для запроса из 2 бд в условие WHERE steam IN(1,2,3,4,5)
    3. Делаем второй запрос в 2 бд - причем сразу указываем сортировку.... зачем сортировать на PHP если это хорошо делает БД

    В итоге: 2 запроса... вместо 1+800-1к

    А по хорошему - пересмотреть архитекутру БД ... что во первых не разные БД были... а еще лучше - все сразу в одной таблице хранилось.. тогда вообще все сделается одним запросом
     
  4. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    Чисто теоретически, в самом запросе возможно указывать базу и выполянть запрос к двум и более разным базам на одном сервере. Это админ должен подтвердить/настроить вам.

    В запросе вместо tablename указывать dbname.tablename,
    а вместо tablename.fieldname указывать dbname.tablename.fieldname

    Код (Text):
    1.  
    2. SELECT o1.email AS email1, o2.email AS email2
    3. FROM development.users AS o1
    4. JOIN development2.users AS o2 ON o1.id = o2.id
    5. ORDER BY o1.id
    6. LIMIT 1
    вот это две базы в одном запросе и оно работает. свой целевой запрос попробуй сочинить сам
     
    JohnWarner и don.bidon нравится это.
  5. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.815
    Симпатии:
    1.332
    Адрес:
    Лень
    А теперь внимание....
    8 строку с prepare выносишь перед циклом while и у автора появляется улыбка от ушей. :)

    Остальное мелочи, мне награду дарвина за исправление не дадут.
    --- Добавлено ---
    24 - 30 строку вообще можно убрать и сделать это все одним запросом с добавлением как огласил @artoodetoo
     
    don.bidon нравится это.