У меня большой запрос MySQL (строки 1.8M, 25 столбцов), и мне нужно сделать из него 2-мерный массив (таблица памяти на основе первичного ключа).
Код работает так, как ожидалось, но создание $table занимает много времени в PHP7.0.
В чем причина того, что PHP7.0 работает намного хуже? Мой основной интерес в mysqli.
Благодарим вас за любые идеи - PHP7 сохранит мне много памяти, если я могу исправить производительность.
фрагмент кода mysqli
$start = microtime(true);
$vysledek = cluster::query("SELECT * FROM `table` WHERE 1");
$query_time = (microtime(true) - $start);
$start_fetch = microtime(true);
while($zaznam = mysqli_fetch_assoc ( $vysledek )){
$fetch_time+= (microtime(true) - $start_fetch);
$start_assign = microtime(true);
$table[$zaznam['prikey']] = $zaznam;
$assign_time+= (microtime(true) - $start_assign);
$start_fetch = microtime(true);
}
$total_time+= (microtime(true) - $start);
echo round($assign_time, 2).' seconds to set the array values\n';
echo round($query_time, 2).' seconds to execute the query\n';
echo round($fetch_time, 2).' seconds to fetch data\n';
echo round($total_time, 2).' seconds to execute whole script\n';
echo "Peak Memory Usage:".round(memory_get_peak_usage(true)/(1024 * 1024), 2)." MB\n";
результаты mysqli
Deb 7 PHP 5.4 mysqlnd 5.0.10
1,8 секунды для установки значений массива
8,37 секунд для выполнения запроса
13.49 секунд для получения данных
24.42 секунды для выполнения целых script
Использование пиковой памяти: 8426,75 МБ
Deb 8 PHP 5.6 mysqlnd 5.0.11-dev
1,7 секунды для установки значений массива
8.58 секунд для выполнения запроса
12,55 секунды для получения данных
23,6 секунды для выполнения целых script
Использование пиковой памяти: 8426,75 МБ
Deb 8 PHP 7.0 mysqlnd 5.0.12-dev
0,73 секунды для установки значений массива
8,63 секунды для выполнения запроса
126,71 секунды для получения данных
136.46 секунд для выполнения целых script
Использование пиковой памяти: 7394,27 МБ
Deb 8 PHP 7.0 mysqlnd 5.0.12-dev расширенный бенчмаркинг
У меня расширенный бенчмаркинг для выборки раздела, чтобы сообщать каждые 100 тыс. строк со следующими результатами:
Линии выбрали 100000 в 1.87s
Линии выбрали 300000 в 5.24s
Линии выбрали 500000 в 10.97s
Линии выбрали 700000 в 19.17s
Линии выбрали 900000 в 29,96s
Линии выбрали 1100000 в 43.03s
Линии выбрали 1300000 в 58.48s
Линии выбрали 1500000 в 76,47s
Линии выбрали 1700000 в 96,73s
Линии выбрали 1800000 в 107.78s
DEB8 PHP7.1.0-dev libclient 5.5.50
1,56 секунды для установки значений массива
8,38 секунды для выполнения запроса
456,52 секунды для получения данных
467,68 секунд для выполнения целых script
Использование пиковой памяти: 8916 МБ
DEB8 PHP7.1.0-dev libclient 5.5.50 расширенный бенчмаркинг
Линии выбрали 100000 в 2.72s
Линии выбрали 300000 в 15,7 с
Линии выбрали 500000 в 38,7 с
Линии выбрали 700000 в 71,69s
Линии выбрали 900000 в 114,8 с
Линии выбрали 1100000 в 168.18s
Линии выбрали 1300000 в 231,69 секунд
Линии выбрали 1500000 в 305,36s
Линии выбрали 1700000 в 389.05s
Линии выбрали 1800000 в 434,71 с
DEB8 PHP7.1.0-dev mysqlnd 5.0.12-dev
1,51 секунды для установки значений массива
9,16 секунды для выполнения запроса
261,72 секунды для получения данных
273,61 секунды для выполнения целых script
Использование пиковой памяти: 8984,27 МБ
DEB8 PHP7.1.0-dev mysqlnd 5.0.12-dev расширенный бенчмаркинг
Линии выбрали 100000 в 3.3s
Линии выбрали 300000 в 13,63s
Линии выбрали 500000 в 29.02s
Линии выбрали 700000 в 49,21s
Линии выбрали 900000 в 74.56s
Линии выбрали 1100000 в 104.97s
Линии выбрали 1300000 в 140.03s
Линии выбрали 1500000 в 180.42s
Линии выбрали 1700000 в 225.72s
Линии, заказанные 1800000 в 250.01s
фрагмент кода PDO
$start = microtime(true);
$sql = "SELECT * FROM `table` WHERE 1";
$vysledek = $dbh->query($sql, PDO::FETCH_ASSOC);
$query_time = (microtime(true) - $start);
$start_fetch = microtime(true);
foreach($vysledek as $zaznam){
$fetch_time+= (microtime(true) - $start_fetch);
$start_assign = microtime(true);
$table[$zaznam['prikey']] = $zaznam;
$assign_time+= (microtime(true) - $start_assign);
$start_fetch = microtime(true);
}
$total_time+= (microtime(true) - $start);
echo round($assign_time, 2).' seconds to set the array values\n';
echo round($query_time, 2).' seconds to execute the query\n';
echo round($fetch_time, 2).' seconds to fetch data\n';
echo round($total_time, 2).' seconds to execute whole script\n';
echo "Peak Memory Usage:".round(memory_get_peak_usage(true)/(1024 * 1024), 2)." MB\n";
Результаты PDO
Deb 7 PHP 5.4 mysqlnd 5.0.10
1,85 секунды для установки значений массива
12,51 секунды для выполнения запроса
16,75 секунд для получения данных
31,82 секунды для выполнения целых script
Использование пиковой памяти: 11417.5 МБ
Deb 8 PHP 5.6 mysqlnd 5.0.11-dev
1,75 секунды для установки значений массива
12,16 секунды для выполнения запроса
15,72 секунды для получения данных
30.39 секунд для выполнения целых script
Использование пиковой памяти: 11417.75 МБ
Deb 8 PHP 7.0 mysqlnd 5.0.12-dev
0,71 секунды для установки значений массива
35,93 секунды для выполнения запроса
114,16 секунды для получения данных
151.19 секунд для выполнения целых script
Использование пиковой памяти: 6620.29 МБ
Сравнительный код базовой линии
$start_query = microtime(true);
exec("mysql --user=foo --host=1.2.3.4 --password=bar -e'SELECT * FROM `profile`.`table`' > /tmp/out.csv");
$query_time = (microtime(true) - $start_query);
echo round($query_time, 2).' seconds to execute the query \n';
Время выполнения аналогично для всех систем в 19 секунд + 1 секунда.
Основываясь на вышеприведенных наблюдениях, я бы сказал, что PHP 5.X разумен, поскольку выполняется немного больше работы, чем просто сбрасывание в файл.
- все 3 сервера находятся на одном хосте (исходный и оба тестовых сервера).
- тесты повторяются при повторении
-
в памяти уже есть аналогичная переменная, мне нужно сделать это для сравненияудалено для тестирования, не связано с проблемой - Процессор на 100% все время
- Оба сервера имеют 32G RAM и swappiness, установленный в 1, целью является выполнение его как операции с памятью.
- тестовый сервер посвящен, больше ничего не работает
- php.ini изменен между основными версиями, но все параметры, относящиеся к mysqli/PDO, кажутся одинаковыми
-
Машина Deb8 была понижена до версии PHP5.6, и проблема исчезла после переустановки PHP7 назад
-
Сообщается об ошибке на php.net - ID 72736, так как я считаю, что было доказано, что проблема заключается в PHP, а не в системе или какой-либо другой конфигурации
Изменить 1: добавлено сравнение PDO
Изменить 2: добавлены маркеры эталонных тестов, отредактированы результаты PDO, так как была ошибка сравнения
Изменить 3: Основная очистка в исходном вопросе, перестроение кода снайперов для лучшего указания ошибки
Изменить 4: добавлен пункт о обновлении и обновлении PHP
Изменить 5: добавлен расширенный бенчмаркинг для DEB8 PHP7.0
Изменить 6: включен php7 config
Изменить 7: измерение производительности для PHP 7.1 dev с обеими библиотеками, скомпилированными с конфигурациями из епископа, удалило мою php-config
Изменить 8: добавлено сравнение с командой CLI, незначительные очистки