Мне всегда казалось, что разница между буферизированными и небуферизованными запросами PHP / MySQL заключается в том, что буферизация (по умолчанию) загружает все данные в переменную набора результатов, а затем вы можете начать использовать их, тогда как небуферизованные загружают строку в время.
Предположим, вы запустили SELECT * FROM sometable
а затем выполнили $result = $db->query($query);
, $result
будет содержать все строки и дополнительную информацию, такую как количество строк. Поэтому, если вы сделали это на базе 100 МБ, вы ожидали бы, что $result
займет ~ 100 МБ, если там не будет индексов).
Тем не менее, я столкнулся с этим вопросом переполнения SO, в котором говорится о буферизованных запросах:
[Результат] будет содержать некоторый буфер строк, зависящий от реализации. Это может быть 100 строк или больше или меньше. Все столбцы возвращаются для каждой строки; Когда вы получаете больше строк, клиент будет запрашивать у сервера больше строк. Это может быть, когда клиент заканчивается, или это может быть сделано превентивно.
Правильно ли, действительно ли происходит буферизация? Если это так, неужели нам вообще не нужно беспокоиться о том, что у PHP заканчивается память при работе с большими наборами результатов? Это странно, потому что я запускал тестовые буферизованные запросы в тестовой таблице 40 МБ, и PHP всегда сообщает о пиковой памяти ~ 5 МБ.
Наконец, как правило, когда вы выбираете небуферизованный буфер? Можете ли вы привести пример?
Благодарю.
(Кстати, я использую MySQLi. Я предполагаю, что принцип тот же).
EDIT: Я читал немного больше и еще более запутался. В http://php.net/manual/en/mysqli.quickstart.statements.php говорится:
On После выполнения результатов выполнения команды можно сразу получить буфер, который будет буферизироваться клиентом, или путем чтения строки за строкой. Буферизация результирующего набора на стороне клиента позволяет серверу освобождать ресурсы, связанные с результатами заявления, как можно раньше. Вообще говоря, клиенты медленно потребляют множество результатов. Поэтому рекомендуется использовать буферизованные результирующие наборы. mysqli_query () объединяет выполнение операторов и буферизацию набора результатов.
Приложения PHP могут свободно перемещаться по буферизированным результатам. Навигация выполняется быстро, потому что результирующие наборы хранятся в клиентской памяти. Пожалуйста, имейте в виду, что его часто проще масштабировать клиентом, чем масштабировать сервер.
И на http://php.net/manual/en/mysqli-result.fetch-all.php говорится:
Поскольку mysqli_fetch_all () возвращает все строки в виде массива за один шаг, он может потреблять больше памяти, чем некоторые подобные функции, такие как mysqli_fetch_array (), который возвращает только одну строку за раз из набора результатов. Кроме того, если вам нужно выполнить итерацию по набору результатов, вам понадобится конструкция цикла, которая будет еще больше влиять на производительность. По этим причинам mysqli_fetch_all () следует использовать только в тех ситуациях, когда полученный набор результатов будет отправлен на другой уровень для обработки.
Это кажется несколько противоречивым. В чем разница между «буферизацией набора результатов на стороне клиента» и «потреблением наборов результатов»? Говорят, что они хранятся в клиентской памяти, а другие говорят, что читаются подряд за строкой. Если все это буферизуется PHP, почему последняя цитата говорит, что если вы вернете все строки в виде массива за один шаг, он может потреблять больше памяти?
См .: http://php.net/manual/en/mysqlinfo.concepts.buffering.php
Небуферизованные запросы MySQL выполняют запрос, а затем возвращают ресурс, пока данные все еще ждут на сервере MySQL для получения. Это использует меньше памяти на стороне PHP, но может увеличить нагрузку на сервер. Если полный набор результатов не был получен с сервера, никакие дальнейшие запросы не могут быть отправлены по одному и тому же соединению. Небуферизованные запросы также можно назвать «результатом использования».
После этих характеристик буферизованные запросы следует использовать в тех случаях, когда вы ожидаете только ограниченного набора результатов или должны знать количество возвращаемых строк перед чтением всех строк. Небуферизованный режим следует использовать, когда вы ожидаете больших результатов.
Буферизованные запросы по умолчанию.
Небуферизованный пример:
<?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(); ?>
надеюсь это поможет