Результаты запроса ORM:Массивы и дескриптор результата, заключенный в интерфейс Iterator

StackOverflow https://stackoverflow.com/questions/531536

Вопрос

Хорошо, вот один для профессионалов:

Вот уже пару лет я работаю над своей собственной реализацией PHP ORM/ActiveRecord, которую я назвал Свинина.dbObject.

Он основан на фильме «Создайте свой собственный сайт с помощью рельсов за 5 минут», который мы все видели пару лет назад.Вы можете делать такие вещи, как:

$clients = dbObject::Search("Client", array("ID > 500")); 

или

$client = new Client(218); // fetch row with id 218 from client table

или

$projects = $client->Find('Project');

Это позволит получить одну или несколько строк из базы данных, обернуть их в dbObject и вернуть в один массив или вернуть false, если результатов нет.

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

Запросы, которые он выполняет, могут возвращать более 20 000 строк, а может быть, и больше, что, конечно, не очень хорошо, если сразу все помещать в оболочку объекта и возвращать как один массив.

Очевидным решением было бы вернуть объект, реализующий Итератор интерфейс вместо массива.Он не должен мгновенно извлекать все записи из набора результатов, а просто хранить ресурс результата для сгенерированного запроса к базе данных и использовать mysql_fetch_* внутри себя, когда вы перемещаетесь по объекту, как если бы это был массив.

Теперь мы подошли к моему реальному вопросу:Могу ли я без проблем просто это сделать?Могут ли базы данных обрабатывать несколько открытых наборов результатов, смешивать их и хранить в памяти какое-то время?

Например, извлеките 20 объектов, зациклите их, пусть каждый из этих 20 извлекает 5 других, которые, в свою очередь, также извлекают 3 других.Это создаст цикл, в котором в памяти будет храниться несколько различных дескрипторов результатов.

Я знаю, что не могу сериализовать один из этих объектов, но смогу ли я без проблем реализовать это в PHP5, или интерфейсы базы данных вызовут у меня проблемы?

Это было полезно?

Решение

Это зависит от того, какую базу данных вы используете и конфигурации вашей базы данных.

Для MySQL вам необходимо убедиться, что вы используете буферизованные запросы.В PDO вы устанавливаете это так:

$myPdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);

Это означает, что все данные будут отправлены клиенту (это не то же самое, что получение всех этих данных в PHP).

Другая (вероятно, худшая) альтернатива — открывать новое соединение с базой данных всякий раз, когда вы обнаруживаете, что выполняется запрос с открытым набором результатов.

Нормальный mysql_query() использует буферизованный запрос, поэтому он будет работать с несколькими наборами результатов.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top