@emerysh

Почему очень долго выполняеться запрос к БД?

Здравствуйте, есть такая вещь:

$db_host = 'localhost';
  $db_user = 'root';
  $db_password = '';
  $db_name = 'price_sites';
  
  $linkps = mysqli_connect($db_host, $db_user, $db_password, $db_name);
    
  $query = "SELECT * FROM table1 LEFT JOIN table2  USING(item)";
  $result = mysqli_query($linkps, $query);	

  $numrows = mysqli_num_rows($result);

    function DrawTableNames()
    {
      global $numrows;
      for($i=0;$i<numrows;$i++){
      echo '\< td \>'; 
      echo mysqli_result($result,$i,'item');
      echo '\< \/td \>';

      }
    } 
    function DrawTableSites($site)
    {
      global $numrows;
      for($i=0;$i<numrows;$i++){
        echo "\< td \>",mysqli_result($result,$i,$site),"\< \/td \>";
      }
    }


Но открывается страница этого скрипта и скрипт начинает свое выполнение -5-10 мин.

Если этот же запрос сделать в phpmyadmin: (99207 всего, Запрос занял 0.0002 сек.)

То есть запрос выполняется быстро, но куда уходит столько времени? Как его убрать?
Еще нашел немного информации об serialize - можно ли этим убрать сию задержку?
  • Вопрос задан
  • 1553 просмотра
Решения вопроса 2
i_d_1
@i_d_1
Программист PHP
зачем функции DrawTableNames и DrawTableSites? где они используюсться? что попадает в циклы for($i=0;$i < numrows;$i++)? может там 1 000 000 000 000 строк?

следующий момент USING(item) item надо пологать есть в обех таблицах. проверьте одинкового ли он типа и размера в обеиз таблицах которые джойните.

и да таблицы диких размеров сторяться исключительно долго. есть вариант как это дело ускорить но незначительно. передавать данные в json. JS на стороне пользователя кушает его и строка за строкой асинзронно формирует табличку в миллиард строк. можно еще отложенную загрузку присобачить с LIMIT тогда все точно будет быстро работать.
Ответ написан
@emerysh Автор вопроса
Решением было переписать все напрочь, сделал "пагинацию", поиск в самом БД, другими словами server-side
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 3
politon
@politon
HTML5,CSS3,JS,PHP,SQL,API,canvas,animation...
Попробуй для начала определить вообще время подключение к БД
<?php
$start = microtime(true); 
$host = 'localhost'; // адрес сервера 
$database = 'price_sites';
$user = 'root'; 
$password = ''; 
$link = mysqli_connect($host, $user, $password, $database) 
    or die("Ошибка " . mysqli_error($link));

mysqli_close($link);
echo 'Скрипт выполнен за: '.(microtime(true) - $start).' сек.';

к примеру у меня 0.008999938964844 сек.
Ответ написан
FanatPHP
@FanatPHP
Чебуратор тега РНР
> Если этот же запрос сделать в phpmyadmin:

phpmyadmin - убогая погремушка для ламеров. измерять по нему скорость выполнения запроса - это все равно что смотреть время на стоящих часах. Два раза в сутки покажет правильно...

Во-первых, phpmyadmin подставляет limit для твоего запроса, и запрашивает всего 20 строк из твоих 100 тысяч. Попробуй запросить все, и посмотри, сколько времени будет выполняться. Если вообще выполнится.
Во-вторых, даже для запроса с лимитом, 0.0002 -это мало. Результат явно идет из квери кеша. Один раз выполнил, дальше запрос закэшировался, и радостро выдает тупо результат.
В-третьих, как тут уже все сказхали, делать таблицу на сто тыщ строк - это совсем за пределами осмысленности. Кто будет это читать? Даже если делаешь XLS.

В общем, сначала изменить, сколкьо времени выполняется запрос ЦЕЛИКОМ, а потом сократить количество запрашиваемых строк до разумных значений.
Ответ написан
NikitaTratorov
@NikitaTratorov
CTO
В свете Вышесказанного, если не менять логику и Вам необходимо получить все строки например, для вывода в CSV или Excel, сделать приблизительно следующее:
//set_time_limit(120); // может понадобиться увеличить время выполнения
$db_host = 'localhost';
$db_user = 'root';
$db_password = '';
$db_name = 'price_sites';
  
$linkps = mysqli_connect($db_host, $db_user, $db_password, $db_name);

$limit = 1000;
$offset = 0;
// выполняем запрос с подсчетом общего числа результатов
$query = sprintf("SELECT SQL_CALC_FOUND_ROWS * FROM table1 LEFT JOIN table2  USING(item) LIMIT %d,%d", $offset,$limit);
$result = mysqli_query($linkps, $query);	

// получаем общее число результатов
$resultTotal = mysqli_query($linkps, "SELECT FOUND_ROWS() AS total");
$res = mysqli_fetch_assoc($resultTotal);
$numrows = $res['total'];

// идем в цикле по результатам
for ($offset = 0; $offset <= $numrows ; $offset += $limit) {
    // получаем строки из результата
    while ($row = mysqli_fetch_assoc($result)) {
        // Что-нибудь делаем с полученной строкой
        print_r($row);
    }
    //запрашиваем очередную порцию данных
    $query = sprintf("SELECT * FROM table1 LEFT JOIN table2  USING(item) LIMIT %d,%d", $offset,$limit);
    $result = mysqli_query($linkps, $query);	
}

Сразу говорю, что код может не заработать, ибо писал на память.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы