У меня есть большой запрос MySQL (строки 1.8M, 25 столбцов), и мне нужно сделать из него 2-мерный массив (таблица памяти на основе первичного ключа).mysqli_fetch_assoc() performance PHP5.4 vs PHP7.0
Код работает, как ожидалось, но создание $ 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 секунд, чтобы установить массив значений
,37 секунд, чтобы выполнить запрос
13.49 секунд для извлечения данных
24,42 секунд, чтобы выполнить весь сценарий
пиковое использование памяти: 8426,75 MB
Deb 8 PHP 5.6 mysqlnd 5.0.11-DEV
1,7 секунд, чтобы установить массив значений
,58 секунд, чтобы выполнить запрос
12,55 секунд, чтобы получить данные
23,6 секунд, чтобы выполнить весь сценарий
пикового использования памяти: 8426,75 MB
Деб 8 PHP 7.0 mysqlnd 5.0.12-DEV
0,73 секунд, чтобы установить массив значений
,63 секунд, чтобы выполнить запрос
126,71 секунд, чтобы получить данные
136.46 секунд, чтобы выполнить весь сценарий
Пик памяти Использование: 7394,27 MB
Deb 8 PHP 7.0 mysqlnd 5.0.12-DEV расширенный бенчмаркинга
я продлил бенчмаркинга п или секция выборки, чтобы сообщить каждую 100k линии со следующими результатами:
линия принесла 100000 в 1.87s
линии принесла 300000 в 5.24s
линии принесла в 10.97s 500000
линий принесла 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 секунд, чтобы установить массив значений
,38 секунд, чтобы выполнить запрос
456,52 секунд, чтобы получить данные
467.68 секунд, чтобы выполнить весь сценарий
Пик Использование памяти: 8916 MB
DEB8 PHP7.1.0-DEV libclient 5.5.5 0 расширенного бенчмаркинга
Линия принесла 100000 в 2.72s
Lines принесло 300000 в 15.7s
линий принесла в 38.7s 500000
линий принесла 700000 в 71.69s
линий принесла 900000 в 114.8s
Линии ушей 1100000 в 168.18s
линии принес 1300000 в 231.69s
линии принес 1500000 в 305.36s
линии принес 1700000 в 389.05s
Линии принесла 1800000 в 434.71s
DEB8 PHP7.1.0-DEV mysqlnd 5.0.12-DEV
1,51 секунд, чтобы установить массив значений
9,16 секунд, чтобы выполнить запрос
261.72 секунд выборки данных
273.61 секунд, чтобы выполнить весь сценарий Использование
Пик памяти: 8984,27 MB
DEB8 PHP7.1.0-DEV mysqlnd 5.0.12-DEV расширенного бенчмаркинг
Линия принесла 100000 в 3.3s
Lines принесло 300000 в 13.63s
линий принесла в 29.02s 500000
линий принесло 700000 в 49.21s
линии принесла 900000 в 74.56s
линий принесли 1100000 в 104.97s
линий принесли 1300000 в 140.03s
линий принесли 1500000 в 180.42s
линий принесли 1700000 в 225.72s
Линии 1800000 принес в 250.01s
ПДО фрагмент кода
$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";
ПДО Результаты
Deb 7 PHP 5.4 mysqlnd 5.0.10
1,85 секунды, чтобы установить массив значения
12.51 секунд, чтобы выполнить запрос
16,75 секунд, чтобы получить данные
31,82 секунд, чтобы выполнить весь сценарий
пиковое использование памяти: 11417,5 MB
Deb 8 PHP 5.6 mysqlnd 5.0.11-DEV
1,75 секунды задать массив значения
12,16 секунд, чтобы выполнить запрос
15,72 секунд, чтобы получить данные
30,39 секунд, чтобы выполнить весь сценарий
пикового использования памяти: 11417.75 MB
Деб 8 PHP 7.0 mysqlnd 5.0.12-DEV
0,71 секунд, чтобы установить массив значений
35,93 секунд, чтобы выполнить запрос
114,16 секунд, чтобы получить данные
151.19 секунд, чтобы выполнить весь скрипт
Пик использования памяти: 6620,29 MB
Базовый код сравнения
$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.сеть - ID 72736, так как я верю, что это было доказано, что проблема заключается в PHP, а не в системе или любой другой конфигурации
Edit 1: Добавлено PDO Сравнение
Edit 2: Добавлено бенчмаркинг маркеров, отредактированные результаты PDO, как были бенчмаркинга ошибкой
Edit 3: Основная очистка в оригинальном вопросе, перестроение кода snipets для лучшего индикации ошибки
Edit 4: добавлен пункт о DownGrade и модернизации PHP
Edit 5: добавлена расширенная бенчмаркинг для DEB8 PHP7.0
Edit 6: включен php7 конфигурации
Редактирование 7: измерение производительности для PHP 7.1 dev с обеими библиотеками - скомпилировано с конфигурациями из епископа, удалено my php-config
Edit 8: добавлено сравнение с командой CLI, небольшие чистые окна
Просто любопытно: вы пробовали то же самое с PDO? –
Чтобы быть понятным, вы загружаете содержимое всего стола и сохраняете его в большом массиве жира? И сохранение второго массива аналогичного размера в памяти? Это, безусловно, не может быть самым эффективным способом сделать это. – Simba
Фактически это чрезвычайно эффективно, в PHP5.4 вы можете сравнить 2 таблицы, как это, из двух разных БД за 40-60 секунд. В то же время операция не блокирует базы данных, вы можете делать отдельные вставки/удаления/обновления, и оригинальное приложение может работать над этими таблицами все время. Еще один момент заключается в том, что вы можете сделать это на разных серверах, так что, если вы исчерпаете память, вы не уничтожаете целевую базу данных. – Zmrzka