Drupal → Views без вызова entity_load()

22.08.2014

Специфика Views 3 такова, что если в представление добавлены поля Field API (использующие views_handler_field_field), то после выполнения запроса к БД вызывается функция entity_load(), которая подгружает все сущности из результатов выборки (см. views_handler_field_field::post_execute()).

При выводе большого числа результатов это создаёт большие накладные расходы, так как за entity_load() стоит hook_entity_load(), на который сторонние модули любят вешать дополнительные sql-и-не-только запросы.

Из ситуации можно выйти вот таким вот нехитрым способом:

/**
 * Implements hook_views_data_alter().
 */
function MODULENAME_views_data_alter(&$data) {
  foreach ($data as $table_name => $table_info) {
    foreach ($table_info as $field_name => $field_info) {
      if (isset($field_info['field']['handler']) && $field_info['field']['handler'] == 'views_handler_field_field') {
        $field_info['field']['handler'] = 'views_handler_field';
        $field_info['title'] .= ' (raw)';
        $field_info['title short'] .= ' (raw)';
        $data[$table_name][$field_name . '_raw'] = $field_info;
      }
    }
  }
}

Здесь на каждое Field API поле, создаётся его "raw" аналог с хэндлером views_handler_field, который не дёргает entity_load():

Хэндлер выводит сырое значение из БД. Форматтеры не доступны, предполагается использование темизации или альтеринга.

Результаты тестов производительности на примере вывода 1000 нод:

Число запросов Время выполнения всех запросов Время генерации страницы
Вывод только поля title 39 11 ms 600 ms
Вывод поля title и body 49 80 ms 1400 ms
Вывод поля title и body (raw) 40 30 ms 900 ms

Итого: при отказе от entity_load() получили уменьшение времени генерации страницы почти на 40%. Причём чем больше включено модулей, использующих hook_entity_load(), тем этот выигрыш будет больше. Тесты проводились на голом друпале.

Написанное актуально для
Views 3
Похожие записи

Комментарии

Добавить комментарий