Результаты запроса ORM: дескрипторы массивов и результатов обернуты в интерфейсе Iterator - PullRequest
2 голосов
/ 10 февраля 2009

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

Уже пару лет я работаю над своей собственной реализацией PHP ORM / ActiveRecord, которую я назвал Pork.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 строк, может быть, даже больше, что, конечно, не очень хорошая вещь, чтобы сразу оборачивать объектную обертку и возвращать как один массив.

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

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

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

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

1 Ответ

2 голосов
/ 10 февраля 2009

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

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

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

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

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

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

...