Наверх

Пара фокусов с xPDO

В разделе «Репосты» расположены чужие статьи, которые мне понравились или показались полезными.

В ходе одного исследования выяснил несколько интересных вещей про xPDO, о которых раньше не задумывался или некогда было проверить. Решил немедленно поделиться. Выборка 1000 ресурсов
$q = $modx->newQuery('modResource', ['id:>' => 0]);
$q->limit(1000);

$q->prepare();
$q->stmt->execute();
$res = $q->stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($res as $v) {
	//echo $v['modResource_pagetitle'];
}
Этот код работает за 0.042197227478 и занимает 33.3 Mb памяти.
$q = $modx->newQuery('modResource', array('id:>' => 0));
$q->limit(1000);

$res = $modx->getCollection('modResource', $q);
foreach ($res as $v) {
	//echo $v->get('pagetitle');
}
А этот уже за 2.15289998055 и занимает 78.3 Mb памяти. В чем же разница? Внимательный зритель уже догадался в чем трюк — в первом примере мы достаем не объекты, а чистые массивы данных, отсюда скорость и экономия памяти. Если нужно просто вывести содержимое объектов на экран — то это способ гораздо быстрее. Обратите внимание, что к полям приписывается имя класса — modResource_ в данном случае. Это можно изменить, используя $q->select('pagetitle'); А если нужно использовать $resource->get(), $resource->set(), $resource->getTVValue() и другие методы объектов — тут второй запрос, помедленнее. Выборка 100 ресурсовТе же 2 выборки, но с $q->limit(100): Без объектов: Память: 17.6 Mb Время: 0.00191211700439 С объектами: Память: 23.6 Mb Время: 0.216797113419 Тут отличие уже не так значительно. Особенно учитывая, что в реальных выводах страниц используется пагинация, и разбивка результатов на 10 — 15 ресурсов за раз. Выборка 1 ресурсаТе же 2 выборки, но с $q->limit(1); показывают закономерную картину: Без объектов: Память: 17.6 Mb Время: 0.00191211700439 С объектами: Память: 17.8 Mb Время: 0.00573897361755 На малой выборке разницы особой нет. ВыводыТут все просто. Когда вам нужна экономия памяти и высокая производительность для выгрузки товаров, например, или генерации карты солидного сайта — используйте первый метод. Если же нужны удобства, или размер выборки небольшой — можно не заморачиваться и делать как обычно. На закуску. А знаете ли вы, что можно составлять запросы вот так:
$sql = "SELECT * FROM {$modx->getTableName('modResource')} WHERE `id` > 0 LIMIT 1000";

$q = new xPDOCriteria($modx, $sql);

$res = $modx->getCollection('modResource', $q);
foreach ($res as $v) {
	//echo $v->get('pagetitle');
}
Это тот же второй вариант, с объектами, но SQL запрос составлен в ручную. С одной стороны — вы можете делать так любые выборки, с другой — таккой запрос не универсален, и на Microsoft SQL это работать не будет. А при использовании $modx->newQuery() — будет, он позаботся о правильном составлении запроса согласно модели. Плюс, newQuery еще дополнительно приведет значения к типам, указанным в модели. То есть, если у вас в модели id указан как int(10), а вы пихаете туда строку — newQuery превратит ее в 0. То есть, приведет к типу int. Как видно, написание запроса вручную нисколько не экономит время. Но позволяет делать сложные выборки. Память: 77.8 Mb Время: 2.14725112915 Ну и самый легкий вариант:
$sql = "SELECT * FROM {$modx->getTableName('modResource')} WHERE `id` > 0 LIMIT 1000";
$q = $modx->prepare($sql);
$q->execute();
$res = $q->fetchAll(PDO::FETCH_ASSOC);

foreach ($res as $v) {
	//echo $v['pagetitle'];
}
Этот метод отрабатывает уже на чистом PDO, вообще без xPDO объектов. Но разница с ног не сшибает: Память: 32.7 Mb Время: 0.0292019844055 Хотя в этом случае не создается здоровенный объект xPDOCriteria. Видимо, кудесники из MODx что-там хорошо наоптимизировали в своем xPDO. Вот такие приемы можно использовать в MODx Revolution. Да, кстати, выборка 3000 ресурсов первым методом проходит за 0.0797028541565 и занимает 64.0 Mb. Вторым — за 6.38202881813 и кушает 194.5 Mb. Для замера времени использовалась функция microtime(true), для памяти — memory_get_usage(true).
Источник: http://bezumkin.ru/sections/xpdo/44/


7 комментариев

  1. Михаил 26 июня 2014, 12:41 # 0
    Хочу замерить время генерации страниц, чтобы сравнить это время со статическими файлами. Подскажите, каким образом это сделать?
    1. Илья Уткин 26 июня 2014, 12:51 # 0
      Просто вставьте в нужное место на странице:
      [[^t^]]
      1. Михаил 26 июня 2014, 16:50 # 0
        Вставил в чанк футера. Не работает.
        modx revo 2.2.14
        1. Илья Уткин 27 июня 2014, 06:42 # 0
          Ошибочка вышла))) Так надо:
          [^t^]
          © http://docs.modx.pro/system/basics/tag-syntax
          1. Михаил 27 июня 2014, 06:51 # +1
            Спасибо!
        2. vlad 22 мая 2015, 07:57(Комментарий был изменён) # 0
          Илья вставляю ваш код в консоль выдает синтатическую ошибку
          $sql = "SELECT * FROM {$modx->getTableName('modResource')} WHERE `id` > 0 LIMIT 1000";
          
          $q = new xPDOCriteria($modx, $sql);
          
          $res = $modx->getCollection('modResource', $q);
          foreach ($res as $v) {
          	//echo $v->get('pagetitle');
          }
          
          или этот
          $sql = "SELECT * FROM {$modx->getTableName('modResource')} WHERE `id` > 0 LIMIT 1000";
          $q = $modx->prepare($sql);
          $q->execute();
          $res = $q->fetchAll(PDO::FETCH_ASSOC);
          
          foreach ($res as $v) {
          	//echo $v['pagetitle'];
          }
          
      2. Михаил 26 июня 2014, 12:55 # 0
        Вот это космос. Спасибо :)

        Авторизация

        через сервис Loginza:


        Шаблоны MODX

        1 2 Дальше »

        Объектная
        модель
        MODX