PHP + MySQL: разница между буферизированными и небуферизованными запросами
Мне всегда казалось, что разница между простыми терминами между буферами PHP и MySQL и небуферизованными запросами заключается в том, что буферизация (по умолчанию) загружает все данные в переменную набора результатов, а затем вы можете начать использовать их, тогда как небуферизованные нагрузки строка за раз.
Скажем, вы запустили SELECT * FROM sometable
, а затем $result = $db->query($query);
, $result
содержали все строки и дополнительную информацию, такую как количество строк. Поэтому, если вы сделали это на базе 100 МБ, вы ожидали бы, что $result
займет ~ 100 МБ, если там не было индексов).
Однако я столкнулся с этим вопросом SO overflow, в котором говорится о буферизованных запросах:
[Результат] будет содержать некоторый буфер строк, зависящий от реализации. Это может быть 100 строк или больше или меньше. Все столбцы возвращаются для каждой строки; Когда вы получаете больше строк, клиент будет запрашивать у сервера больше строк. Это может быть, когда клиент исчерпал себя или это можно сделать превентивно.
Правильно ли, действительно ли происходит буферизация? Если это так, неужели нам вообще не нужно беспокоиться о том, что у PHP заканчивается память при работе с большими наборами результатов? Это странно, потому что я запускал некоторые тестовые буферизованные запросы в тестовой таблице 40 МБ, и PHP всегда сообщает о потреблении пиковой памяти ~ 5 МБ.
Наконец, как правило, когда вы выбираете небуферизованный буфер? Можете ли вы привести пример?
Спасибо.
(Кстати, я использую MySQLi. Я предполагаю, что принцип тот же).
EDIT: Я прочитал немного больше и еще более смущен. На http://php.net/manual/en/mysqli.quickstart.statements.php говорится
Вкл. После выполнения результатов выполнения команды можно сразу получить буферизацию с помощью клиента или путем чтения строки за строкой. Буферизация результирующего набора на стороне клиента позволяет серверу освобождать ресурсы, связанные с результатами заявления, как можно раньше. Вообще говоря, клиенты медленно потребляют множество результатов. Поэтому рекомендуется использовать буферизованные результирующие наборы. mysqli_query() объединяет выполнение операторов и буферизацию набора результатов.
Приложения PHP могут свободно перемещаться по буферизированным результатам. Навигация выполняется быстро, потому что результирующие наборы хранятся в клиентской памяти. Пожалуйста, имейте в виду, что его часто проще масштабировать клиентом, чем масштабировать сервер.
И на http://php.net/manual/en/mysqli-result.fetch-all.php говорится:
Так как mysqli_fetch_all() возвращает все строки в виде массива за один шаг, он может потреблять больше памяти, чем некоторые подобные функции, такие как mysqli_fetch_array(), который возвращает только одну строку за раз из набора результатов. Кроме того, если вам нужно выполнить итерацию по набору результатов, вам понадобится конструкция цикла, которая будет еще больше влиять на производительность. По этим причинам mysqli_fetch_all() следует использовать только в тех ситуациях, когда полученный набор результатов будет отправлен на другой уровень для обработки.
Это кажется несколько противоречивым. Какая разница между "буферизацией набора результатов на стороне клиента" и "потреблением наборов результатов"? Говорят, что они хранятся в клиентской памяти, а другие говорят, что читаются подряд за строкой. Если все это буферизуется PHP, почему последняя цитата говорит, что если вы вернете все строки в виде массива за один шаг, он может потреблять больше памяти?
Ответы
Ответ 1
Смотрите: http://php.net/manual/en/mysqlinfo.concepts.buffering.php
Небуферизованные запросы MySQL выполняют запрос, а затем возвращают ресурс пока данные все еще ждут на сервере MySQL для получения. Это использует меньше памяти на стороне PHP, но может увеличить нагрузку на сервер. Если полный набор результатов не был получен с сервера no дальнейшие запросы могут быть отправлены по одному и тому же соединению. Unbuffered запросы также могут упоминаться как "результат использования".
После этих характеристик буферизованные запросы должны использоваться в случаях, когда вы ожидаете только ограниченного набора результатов или должны знать количество возвращаемых строк перед чтением всех строк. Небуферизованный режим следует использовать, когда вы ожидаете больших результатов.
Буферизованные запросы по умолчанию.
Небуферизованный пример:
<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");
$uresult = $mysqli->query("SELECT Name FROM City", MYSQLI_USE_RESULT);
if ($uresult) {
while ($row = $uresult->fetch_assoc()) {
echo $row['Name'] . PHP_EOL;
}
}
$uresult->close();
?>
надеюсь, что это поможет