Модуль Views один из самых популярных модулей на Drupal сайтах. Думаю, он включен практически на всех сайтах построенных на Drupal. В этой статье я бы хотел описать проблемы с производительностью Views с которыми я столкнулся работая с этим модулем в Drupal 8 и способы оптимизации.
Проблема вывода большого количества сущностей во Views
Отличительной особенностью Views в Drupal 8 от Views в Drupal 7 является то, что в восьмерке Views загружает всю сущность всякий раз, даже если нужно отобразить одно поле (Drupal\views\Plugin\views\cache\CachePluginBase). Если вам нужно показать на одной странице 10 или 100 элементов, то загрузка такого количества нод не будет проблемой. Но если вам нужно будет отобразить 1000 сущностей, то их загрузка не будет быстрой, особенно если в сущности много полей. Кроме длительной обработки Views вы можете столкнуться с ограничением памяти в PHP. Если вы используете shared hosting, то это может быть серьезной проблемой т.к. зачастую там нет возможности прибавить память.
Поэтому для вывода полей из большого количества сущностей одновременно (больше 500) я бы рекомендовал рассмотреть возможность реализовать блок, в котором бы загружались только нужные поля через sql запрос. Да, придется потратить на это время и реализовать самостоятельно, но только так вы сможете избежать загрузки всех сущностей и увеличить скорость обработки страницы.
Если вы используете SOLR в качестве хранилища данных, то ознакомьтесь со статьей Create a search view that doesn’t load entities from the database, которая расскажет как избежать загрузки сущностей во views при использовании SOLR.
Если вы используете такие модули как Views selective filters или Selective better exposed filters, то вы должны знать, что эти модули запускают views еще раз с выводом абсолютно всех значений для построения каждого селективного фильтра.
Например, если у нас есть 1000 нод, то не проблема отобразить их постранично по 10 сущностей на странице. Но если мы добавили 2 селективных фильтра, то тогда будет запускаться эта views с отображением 10 сущностей, а также 2 раза эта views c выводом 1000 нод для построения селективных фильтров. Можете себе представить, как это скажется на производительности. Так что если у вас несколько сотен сущностей и пара селективных фильтров, то эти модули могут использоваться. Но если у вас тысячи нод, то я бы рекомендовал реализовать плагин для фильтра views, где вы сможете подготовить данные, самостоятельно.
Увеличиваем срок жизни кеша во Views
Следующее, что стоит отметить, является то, как Views работает с кешем. Во views результаты кешируются постранично (Drupal\views\Plugin\views\cache\CachePluginBase). Этот кеш с результатами помечается специальным тегом вида [ENTITY_TYPE]_list (например, node_list, taxonomy_term_list, media_list). Тег сбрасывается каждый раз когда сущность добавляется, обновляется или удаляется. В общем, при любых операциях с сущностью. Это нужно, чтобы views знала когда нужно обновлять кеш с результатами, чтобы новая сущность попала во views.
Проблема тут заключается в том, что при обновлении любой сущности кеш у всех views, которые выводят сущности такого же типа, будет очищаться.
Чтобы увеличить срок кеша views мы можем взять патч из https://www.drupal.org/project/drupal/issues/2145751 (вполне возможно, что в Drupal 9 это будет в ядре), который предоставляет листинг тег [ENTITY_TYPE]_list:[BUNDLE]. При обновлении сущности будут сбрасываться теги [ENTITY_TYPE]_list и [ENTITY_TYPE]_list:[BUNDLE].
Затем устанавливаем модуль Views custom cache tag. Этот модуль предоставляет возможность указывать теги для кеша views вручную. Прописываем во views листинг теги для тех сущностей, которые в нём используются:
В моем примере views выводит список нод типа Page, а также используются фильтры с терминами таксономии One, Two, Three. Теперь кеш этой views будет очищаться только если ноды Page или термины в словарях One, Two или Three были обновлены.
Кешируем ajax запросы во Views
Одной из лучших практик кеширования запросов для анонимных пользователей является использование reverse proxy, например Varnish. Проблема в том, что они не кешируют POST запросы, а именно такие запросы создаются если ajax включен во views.
Чтобы исправить это мы можем воспользоваться модулем Views ajax get. Он расширяет стандартную Drupal ajax библиотеку и заменяет тип запроса с POST на GET для ajax запросов во views. После установки и включения модуля нужно в настройках views “Use AJAX” поставить галочку “Use GET requests”.
Таким очень простым способом можно серьезно снизить нагрузку на сервер и увеличить скорость отдачи ajax запросов во views, при условии что вы используете reverse proxy для кеширования на проекте.
Вывод
Модуль Views является очень мощным и универсальным решением. Он спроектирован для того, чтобы с помощью него можно было быстро и легко решать типовые задачи по выводу контента. Но если ваши задачи выходят за рамки типовых, то могут начаться проблемы. Анализируйте текущее состояние вашего сайта, смотрите на свои требования и не бойтесь реализовывать оптимизированные решения для вашего проекта - views предоставляет широкие возможности для расширения функционала.