Время выполнения SQL запросов PHP


Как узнать время выполнения MySQL запроса?

Одним из главных факторов эффективности выполнения MySQL запросов является время его выполнения. Отладка запросов MySQL является делом не из редких, и хорошо бы иметь под рукой удобный инструмент, который бы позволил оценить время выполнения запроса.
В MySQL начиная с версии 5.0.37 есть появился встроенный механизм — profiling, который позволяет оценить время выполнения того или иного запроса.

Рассмотрим пример его использования:

В качестве результата получаем данные в таком виде:

Команда show profiles по умолчанию показывает результаты 15 запросов, цифру можно увеличить, задав параметр profiling_history_size:

Этот метод так же хорош тем, что если мерить время выполнения запроса из самого кода приложения, то такие факторы, как коннект к серверу MySQL тоже может отнимать какое-то время, что в итоге может привести к неточным цифрам. В случае же с профилированием, вы просматриваете время выполнения самого запроса. Кроме этого можно просмотреть детальную информацию, на что тратилось время выполнения запроса:

Довольно удобный инструмент, который можно использовать для оптимизации MySQL запросов.
Узнайте больше о возможностях использования в официальной документации — SHOW PROFILE Syntax.

Время выполнения запросов mysql

Poster

Новичок

Время выполнения запросов mysql

Доброго!
Заскеаю время в скрипте,

затем идет буквально один запрос

Сразу после запроса — еще отдна засечка времени.

В итоге имеем время до и после запроса
0.00085 s

Подскажите пожалуйста куда запрос жрет столько времени?

Буквально после каждого запроса в скрипте время увеличивается раза в два, под конец имеем примерно 0.03-0.5 с
Куда копать? В индексы?

fixxxer

Poster

Новичок

mysql> explain section;
+——————+—————+——+——+———+—————-+
| Field | Type | Null | Key | Default | Extra |
+——————+—————+——+——+———+—————-+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| alias | varchar(100) | NO | MUL | | |
| level | tinyint(4) | NO | MUL | 0 | |
| parent | bigint(20) | NO | MUL | 0 | |
| sort | bigint(20) | NO | | 0 | |
| type | tinyint(4) | NO | MUL | 2 | |
| cat | int(1) | NO | | 0 | |
| slu | enum(‘y’,’n’) | NO | | y | |
| email | varchar(255) | NO | | | |
| color | varchar(32) | NO | | | |
| classe | char(3) | NO | | | |
| ban_prop | varchar(32) | NO | | | |
| showm | enum(‘y’,’n’) | NO | | n | |
| quantity_on_page | int(3) | NO | MUL | 0 | |
| showexgb | enum(‘y’,’n’) | NO | | y | |
| showalb | enum(‘y’,’n’) | NO | | n | |
| rightmenu | enum(‘y’,’n’) | NO | | n | |
| img | varchar(255) | NO | | | |
| img2 | varchar(255) | NO | | | |
| person_price | decimal(15,2) | NO | | | |
| groupe_price | decimal(15,2) | NO | | | |
+——————+—————+——+——+———+—————-+

mysql> explain section2;
+———-+—————+——+——+———+——-+
| Field | Type | Null | Key | Default | Extra |
+———-+—————+——+——+———+——-+
| id1 | bigint(20) | NO | MUL | 0 | |
| tochild | enum(‘y’,’n’) | NO | | n | |
| name | varchar(255) | NO | | | |
| img | varchar(255) | NO | | | |
| flashimg | varchar(255) | NO | | | |
| imgmap | text | NO | | | |
| text | text | NO | | | |
| text2 | text | NO | | | |
| lang | int(1) | NO | | 0 | |
| active | enum(‘y’,’n’) | NO | | y | |
+———-+—————+——+——+———+——-+

лучше не получается сюда вставить, сплющивает

Время выполнения SQL запросов PHP

За выполнение запросов отвечают функции mysqli_query() , mysqli_real_query() и mysqli_multi_query() . Чаще всего применяется функция mysqli_query() , так как она выполняет сразу две задачи: выполняет запрос и буферизует на клиенте результат этого запроса (если он есть). Вызов mysqli_query() идентичен последовательному вызову функций mysqli_real_query() и mysqli_store_result() .

Пример #1 Подключение к MySQL

= new mysqli ( «example.com» , «user» , «password» , «database» );
if ( $mysqli -> connect_errno ) <
echo «Не удалось подключиться к MySQL: (» . $mysqli -> connect_errno . «) » . $mysqli -> connect_error ;
>

if (! $mysqli -> query ( «DROP TABLE IF EXISTS test» ) ||
! $mysqli -> query ( «CREATE TABLE test(id INT)» ) ||
! $mysqli -> query ( «INSERT INTO test(id) VALUES (1)» )) <
echo «Не удалось создать таблицу: (» . $mysqli -> errno . «) » . $mysqli -> error ;
>
?>

Буферизация результатов запроса

После выполнения запроса его результаты можно целиком буферизовать на клиенте, либо читать построчно с сервера. Буферизация на клиенте позволяет серверу как можно быстрее освобождать занятые запросом ресурсы. Построчное же чтение и дальнейшая обработка результатов клиентом довольно медленный процесс. Поэтому рекомендуется использовать буферизацию результирующих наборов. Функция mysqli_query() совмещает в себе операции выполнения запроса и буферизации результирующего набора.

PHP-приложения могут свободно оперировать данными внутри буферизованных результирующих наборов. Быстрая навигация по строкам наборов обусловлена тем, что наборы полностью располагаются в памяти клиента. Следует помнить, что зачастую обработка результатов на клиенте проще, нежели средствами сервера.

Пример #2 Навигация по строкам буферизованной результирующей таблицы

= new mysqli ( «example.com» , «user» , «password» , «database» );
if ( $mysqli -> connect_errno ) <
echo «Не удалось подключиться к MySQL: (» . $mysqli -> connect_errno . «) » . $mysqli -> connect_error ;
>

if (! $mysqli -> query ( «DROP TABLE IF EXISTS test» ) ||
! $mysqli -> query ( «CREATE TABLE test(id INT)» ) ||
! $mysqli -> query ( «INSERT INTO test(id) VALUES (1), (2), (3)» )) <
echo «Не удалось создать таблицу: (» . $mysqli -> errno . «) » . $mysqli -> error ;
>

Мастер Йода рекомендует:  20 лучших расширений Google Chrome для веб-дизайнеров

$res = $mysqli -> query ( «SELECT id FROM test ORDER BY id ASC» );

echo «Обратный порядок. \n» ;
for ( $row_no = $res -> num_rows — 1 ; $row_no >= 0 ; $row_no —) <
$res -> data_seek ( $row_no );
$row = $res -> fetch_assoc ();
echo » > . $row [ ‘id’ ] . «\n» ;
>

echo «Исходный порядок строк. \n» ;
$res -> data_seek ( 0 );
while ( $row = $res -> fetch_assoc ()) <
echo » > . $row [ ‘id’ ] . «\n» ;
>
?>

Результат выполнения данного примера:

Небуферизуемые результирующие наборы

Если клиентские ресурсы ограничены, и в тоже время не требуется поддерживать низкую нагрузку на сервер, можно использовать не буферизованные результирующие наборы. Навигация по таким таблицам невозможна, потому что так или иначе должны быть обработаны все строки набора.


Пример #3 Навигация по строкам небуферизованной результирующей таблицы

-> real_query ( «SELECT id FROM test ORDER BY id ASC» );
$res = $mysqli -> use_result ();

echo «Порядок строк в результирующем наборе. \n» ;
while ( $row = $res -> fetch_assoc ()) <
echo » > . $row [ ‘id’ ] . «\n» ;
>
?>

Типы данных значений в результирующей таблице

Функции mysqli_query() , mysqli_real_query() и mysqli_multi_query() предназначены для выполнения неподготавливаемых запросов. На уровне протокола клиент-серверного взаимодействия MySQL за выполнение запросов отвечают команда COM_QUERY и текстовый протокол. Когда используется текстовый протокол, сервер MySQL перед отправкой клиенту преобразует все данные в результирующем наборе в текстовые строки. Это преобразование выполняется вне зависимости от типа данных SQL-столбца результирующей таблицы. Клиентские библиотеки mysql, в свою очередь, получают все данные, принимая их за строки. На клиенте не проводится никакого обратного преобразования к исходным типам, все данные, полученные приложением остаются PHP строками.

Пример #4 Текстовый протокол по умолчанию возвращает строки

= new mysqli ( «example.com» , «user» , «password» , «database» );
if ( $mysqli -> connect_errno ) <
echo «Не удалось подключиться к MySQL: (» . $mysqli -> connect_errno . «) » . $mysqli -> connect_error ;
>

if (! $mysqli -> query ( «DROP TABLE IF EXISTS test» ) ||
! $mysqli -> query ( «CREATE TABLE test(id INT, label CHAR(1))» ) ||
! $mysqli -> query ( «INSERT INTO test(id, label) VALUES (1, ‘a’)» )) <
echo «Не удалось создать таблицу: (» . $mysqli -> errno . «) » . $mysqli -> error ;
>

$res = $mysqli -> query ( «SELECT > );
$row = $res -> fetch_assoc ();

printf ( » > , $row [ ‘id’ ], gettype ( $row [ ‘id’ ]));
printf ( «label = %s (%s)\n» , $row [ ‘label’ ], gettype ( $row [ ‘label’ ]));
?>

Результат выполнения данного примера:

Если используется библиотека mysqlnd, можно включить преобразование целочисленных значений и чисел с плавающей запятой из столбцов таблицы в PHP числа. Делается это заданием настройки подключения MYSQLI_OPT_INT_AND_FLOAT_NATIVE . В таком случае mysqlnd будет проверять метаданные столбцов и преобразовывать SQL-числа этих полей в PHP-числа, если эти значения не выходят за рамки допустимых диапазонов типов данных PHP. То есть, например, SQL INT число попадет в PHP приложение в виде целого (integer).

Пример #5 Получение исходных типов данных в приложении

= mysqli_init ();
$mysqli -> options ( MYSQLI_OPT_INT_AND_FLOAT_NATIVE , 1 );
$mysqli -> real_connect ( «example.com» , «user» , «password» , «database» );

if ( $mysqli -> connect_errno ) <
echo «Не удалось подключиться к MySQL: (» . $mysqli -> connect_errno . «) » . $mysqli -> connect_error ;
>

if (! $mysqli -> query ( «DROP TABLE IF EXISTS test» ) ||
! $mysqli -> query ( «CREATE TABLE test(id INT, label CHAR(1))» ) ||
! $mysqli -> query ( «INSERT INTO test(id, label) VALUES (1, ‘a’)» )) <
echo «Не удалось создать таблицу: (» . $mysqli -> errno . «) » . $mysqli -> error ;
>

$res = $mysqli -> query ( «SELECT > );
$row = $res -> fetch_assoc ();

printf ( » > , $row [ ‘id’ ], gettype ( $row [ ‘id’ ]));
printf ( «label = %s (%s)\n» , $row [ ‘label’ ], gettype ( $row [ ‘label’ ]));
?>

PHP. Является ли время выполнения рассчитывается, когда SQL запроса в ходе

December 2020

24 раз

Если я уже давно работает SQL запрос в моем PHP скрипт, это время выполнения запроса добавляется к общему времени выполнения сценария?

Например, если мой SQL запрос выполняется 25 секунд, а затем я сделать что-то еще в течение 6 секунд в сценарии, то будет «Максимальное время выполнения 30 секунд» произойдет?

1 ответы

On Unix, no — waiting on external services (API calls, databases, etc) does not count towards the max execution time. On Windows, the time refers to the actual wall-clock time.

The set_time_limit() function and the configuration directive max_execution_time only affect the execution time of the script itself. Any time spent on activity that happens outside the execution of the script such as system calls using system(), stream operations, database queries, etc. is not included when determining the maximum time that the script has been running. This is not true on Windows where the measured time is real.

PHP ADOdB Время выполнения запроса SQL

Использование ADOdb для доступа к MS SQL Server в приложении с интенсивным использованием базы данных. Несколько запросов и хранимых процедур выполняются дольше 30 секунд, а ADODB создает исключение для таймаута запроса. Для настройки таймаута нет настройки ADOdb. Установка более длительного тайм-аута команды в SQL Server не работает, поскольку, по-видимому, это время в драйвере ADOdb.PHP ADOdB Время выполнения запроса SQL

Мастер Йода рекомендует:  HTML программирование

Как увеличить время ожидания команды?

ответ

Я действительно сталкивался с этим вопросом раньше. Ошибка, которую я получал, была:

Если это ошибка, которую вы получаете, то я могу быть в состоянии помочь. Первый ответ — посмотреть на ваш фактический запрос и посмотреть, можете ли вы его оптимизировать. Если предположить, что уже было сделано, вы должны открыть ADODB/ADODB-ado5.inc.php или ADODB/ADODB-ado.inc.php в зависимости от того, какую версию PHP вы используете.

В этом файле найдите function _connect . Вы хотите, чтобы изменить его от этого:

$ dbc-> CommandTimeout = 120;

Как получить время выполнения запроса MySQL из PHP?

Я выполняю MySQL-запросы с PHP и хотел бы знать, сколько времени они занимают. Есть ли способ получить время выполнения запроса MySQL из PHP?

Я также задаюсь вопросом, зависит ли время выполнения от того, насколько загружен веб-сервер. Я могу представить, что для выполнения запроса потребуется больше времени, если сервер занят другими запросами. С другой стороны, я могу представить, что если сервер занят, запрос будет просто ждать своего хода, а затем он будет выполнен (без каких-либо запросов, выполняемых параллельно), а время ожидания не будет включено во время выполнения , Итак, какие сценарии (из двух) верны?

SQL-запрос на PHP

Так как ORM слишком тяжеловесны для моих нужд, то обычно я использовал DbSimple. Однако после знакомства с Twig, которые компилирует шаблоны в php код периодически возникала идея написать что-то аналогичное для работы с БД. И вот я это сделал. На картинке представлен запрос на PHP, который после компиляции генерирует код для создания и выполнения SQL запроса.

В первой реализации я компилировал запрос из синтаксиса аналогичного DbSimple в PHP код. Идея была в том, чтобы на выходе получить готовый код с нативными функциями без всяких оберток. При этом можно было наворачивать запросы любой сложности и скорость их разбора не влияла на время работы, так как после компиляции это был обычный нативный код. Однако сложность в отладке таких запросов (сложно было искать ошибки в синтаксисе SQL) и тот факт что время разбора запроса не так велико по сравнению с выполнением запроса привели к тому, что от идеи использовать такой подход я отказался.

Не так давно наткнулся на библиотеку по разбору PHP кода на лексемы PHP-Parser. По работе я пишу код на языке ABAP, в котором команды по работе с БД встроены в сам язык, поэтому возникла идея «А что если сделать что-то подобное для PHP»?


Схема реализации достаточно простая и очевидная: при автозагрузке класса проверяем его наличие в директории компилированных классов. Если нет скомпилированного класса, то берем исходный файл класса, заменяем в нем все спец-команды и записываем готовый класс в директорию скомпилированных классов. Весь разбор делает библиотека PHP-Parser. Чтобы компилятор мог понять, что это именно нужная ему команда, оборачиваем все в пространство имен ML (Macro Language). К примеру в коде пишем так:

и получаем на выходе:

При этом мы можем использовать в запросе непосредственно переменные PHP (которые подставляются в запрос с защитой от SQL-инъекций в PHP и MySQL) и функцию условного формирования запроса _if. В частности такой код:

скомпилируется в такой код:

Так как схема реализации простая, то решил не ограничиваться только SQL. Для этого в коде ищутся не конкретные команды \ML\SQL, а все вызовы из области имен \ML. Если такой вызов находится, то проверяется наличие класса \ML\ . Если такой класс есть, то создается объект этого класса и вызывается его метод ->compile(. ), в который передаются лексемы текущего вызова (корневой узел, полученный от PHP-Parser) + сам объект этого класса. Это позволит использовать данный подход не только для обращения к БД, но и для других нужд (пока не придумал каких :)). В частности планирую сделать расширение ORM над SQL. Т.е. вызов \ML\ORM буду компилировать в код \ML\SQL, который уже будет компилироваться в код PHP. При этом так как время разбора выражения не важно, то при разборе ORM вызова можно потратить время на чтение информации о сущностях, их связях, полях и т.д.

Мастер Йода рекомендует:  Архивы таксономии Вывод списка постов по типу записи

P.S. Хотя прежде чем делать ORM, добавлю команду JOIN + команды UPDATE и DELETE.

Для тех, кому интересно, небольшой тестовый полигон для компиляции кода. Если найдете какую-то ошибку, пишите в комментариях. Пока это версия 0.1 alpha так что ошибки весьма вероятны.

Профайлинг запросов MySql в PHP

Часто в нашем приложении мы хотим узнать, сколько времени выполняется тот или иной запрос. Например, мы хотим отлавливать медленные запросы и уведомлять об нас этом. Как это делается — в этой статье

Задача: есть php-скрипт, выполняющий sql-запросы. Нам необходимо узнать время выполнения каждого запроса. В примере будем использовать объект mysqli. Делаем это так:

‘; // Получим время выполнения и строку sql-запроса $duration = $row[‘Duration’]; $query = $row[‘Query’]; printf(‘Запрос: %s. Время выполнения — %s’, $query, $duration);

Время выполнения SQL запросов PHP

Подписывайся на YouTube канал о программировании, что бы не пропустить новые видео!

Время выполнения SQL запросов
Автор: Barbos www.WebClass.ru

Итак, нам нужно засечь время, потраченное на выполнение SQL запросов ? Это не очень легко, но и не сложно. Начнем с определения задачи. Необходимо выдать полное время, затраченное на генерацию страницы и время, затраченное на выполнения SQL запросов, еще было бы здорово вывести процент от общего времени.

Сначала напишем функцию, которая выдает время, затраченное на выполнение своего кода:
function do_something() <
$mtime = microtime();
$mtime = explode(» «,$mtime);
$mtime = $mtime[1] + $mtime[0];
$tstart = $mtime;
//here is the code to execute
//.

$mtime = microtime();
$mtime = explode(» «,$mtime);
$mtime = $mtime[1] + $mtime[0];
$tend = $mtime;
$tpassed = ($tend — $tstart);
return($tpassed);
>

Для конкретно нашей задачи, нужно модифицировать эту функцию так, чтобы выполнялись SQL запросы:
//запрос передается как аргумент
function do_query($query) <
//подсоединяем две глобальные переменные
global $result;
global $qnum;
//счетчик запросов
$qnum++;
//засекаем время старта
$mtime = microtime();
$mtime = explode(» «,$mtime);
$mtime = $mtime[1] + $mtime[0];
$tstart = $mtime;
//выполняем запрос
$result = MYSQL_QUERY($query);
//засекаем время окончания
$mtime = microtime();
$mtime = explode(» «,$mtime);
$mtime = $mtime[1] + $mtime[0];
$tend = $mtime;
$tpassed = ($tend — $tstart);
//возвращаем время, затраченное на запрос
return($tpassed);
>

Теперь у нас есть функция, которая считает запросы и выдает время экзекуции 🙂 Вот как она должна быть использована:
//Не забудьте где-нибудь в начале скрипта объявить эти две переменные:
$result=0;
$qnum=0;
//.
//Вызов функции:
$sql_time+=do_query(«SELECT * FROM SOME_TABLE»);
//Теперь можно разбирать полученные данные:
while($row = mysql_fetch_array($result)) <
print($row[‘Text’]);
>

В окончательном скрипте нужно еще засечь полное время выполнения, таким же способом, что использовался в функции. Внизу код такого скрипта, который заработает, если вы вставите реальные SQL запросы и подсоединитесь к базе данных.

Вот и все ! 🙂

Опубликовал Kest Ноябрь 02 2008 17:24:18 · 0 Комментариев · 6316 Прочтений ·

• Не нашли ответ на свой вопрос? Тогда задайте вопрос в комментариях или на форуме! •

Комментарии
Нет комментариев.
Добавить комментарий

Рейтинг доступен только для пользователей.

Пожалуйста, залогиньтесь или зарегистрируйтесь для голосования.

Вы не зарегистрированны?
Нажмите здесь для регистрации.

Забыли пароль?
Запросите новый здесь .

Форум PHP программистов ► PHP практикум ► PHP + SQL

Рейтинги

Пейджер выключен!

Профиль
Группа: Пользователь
Сообщений: 3
Пользователь №: 41818
На форуме:
Карма:

Добрый день.
Не могу понять причину длительного выполнения запроса. Есть таблица, которая содержит несколько миллионов записей. В phpmyadmin запускаю на выполнение запрос — выполняется за 10 секунд. Тот же самый запрос запускаю из программы стандартной командой mysql_query — выполняется за 570 секунд. Что только не делал, но никак подвижек. Все другие запросы в ПО исполняются как положено.

Это сообщение отредактировал Ballatus — 11.09.2015 — 19:29

Сообщений: 6111
Пользователь №: 35718
На форуме:
Карма: 196

Профиль
Группа: Пользователь
Сообщений: 3
Пользователь №: 41818
На форуме:
Карма:

Сидел он, дум великих полон — и вдаль глядел

Сообщений: 15707
Пользователь №: 4190
На форуме:
Карма: 485

Цитата (Ballatus @ 11.09.2015 — 23:49)
Я специально решил не загружать форумчан структурами и дампами (да и данные очень конфиденциальные), т.к. уверен, что проблема не в этом.

«Доктор, полечите меня, только я не покажу больной орган — уж больно интимный вопрос»

Если хочешь, чтобы тебе помогли, то исходные данные давай. А если ты знаешь ответ, то зачем спрашиваешь?
Кстати говоря, дампы твои нафиг никому не упали. Думаешь, кто-то будет грузить себе многомиллионные данные?

Да и 10 секунд — многовато. Скорее всего, у тебя или структура данных неправильная (например, нет важного индекса) или запрос кривой. Если, конечно, ты не выбираешь слишком много данных. Но без структуры БД и запроса на этот вопрос не ответит никто. «Телепатов нету» (с)

* Обучаю PHP, JS, вёрстке. Интерактивно и качественно. За разумные деньги.

* «накапливаю умение телепатии» (С) и «гуглю за ваш счет» (С)

Добавить комментарий