Do Views Make Your Drupal Site Slow?
The short answer is yes. I was able to shave 40% off the uncached response time of one page with four views by refactoring it to use the Entity Field Query API. The downside was moving quick and easy configuration through the Drupal Views admin screens into "Drupalese" PHP code. Views are faster to build but run more slowly and are harder to maintain with version control than code.
The Drupal Views module is the most powerful way to query lists of data for presentation to users. It has a robust API and more than a hundred plugins and modules. Everything from shopping cart catalog pages, lists of blog articles, to slideshows and the lists of items that show up in a dropdown, are fairly easily created with Views. A typical home page or complex search page may have four or more views. It is amazing how much you can build with Drupal without programming a line of PHP if you know how to use Views along with Display Suite and Panels.
All this Views goodness comes with three main drawbacks:
- Views are stored in the database. If you're a professional programmer, you're used to putting your complex queries in your code. You build locally, commit to source control, push to staging, test it, then push it to production with the client's approval. While it is possible to import and export views with Views Export, the workflow is not conducive to developer workflow. My usual practice is to build a view locally, then export it, copy, and paste the view code into the "import view" form on the production site.
- Views can be slow and heavy. While you can use page caching for non-logged-in users, the experience will be slower for logged in users, such as site administrators.
- If you give any of your users/clients access to the Views admin, some of them will try to make improvements themselves rather than call you. Sometimes this works out; often it doesn't. In the original article on "Drupal without Views", the author cites this as the main motivation - their clients were going to be using Views, and Phase2 didn't want those users messing up Phase2's work.
I decided to find out just how slow Views are with some informal sleuthing using Apache Benchmark on my local machine. I updated the local copy of one of my favorite websites, the Finger Lakes Native Plant Society (http://flnps.org). Its home page has four views: a slideshow, an upcoming event list, a list of upcoming non-FLNPS events, and a featured native plant.
First, I ran this command to simulate 100 total requests, with four going at any given time:
[sourcecode lang="shell"]$ ab -n 100 -c 4 http://flnps.dev/[/sourcecode]
The results were surprising. 42.35 requests per second with mean time per request of 24ms. Nice!
Then I remembered that page caching was turned on. So I ran "drush vset cache 0 -y" and re-ran the benchmark. Performance fell to 1.20 requests per second with a mean time of 830ms.
Now I began to refactor the four views into custom blocks that query their data using Drupal 7's built-in Entity Field Query API. The basic idea is you create a custom module, add a block for each view, then in the block function you build the dataset using EFQ, then send that data to a theme template for rendering.
With the views refactored to EFQ blocks, the benchmark jumped to 2.02 requests per second, with a time per request of 495ms - a savings of 335ms.
While that's a 40% savings, I wondered if removing Panels might help more. So I deleted my "Home Page" display mode and rebuilt it in a custom tpl.php. Requests per second went to 2.28, with time per request of 438ms. Not insignificant but hardly revolutionary. Display Suite is pretty fast - night and day compared to the Page Manager module.
So should you stop using Views and harvest that 40% savings? It depends. I now use custom blocks for the simple stuff like I just did - blocks on the home page that pull some recent news items or images for a slideshow. I would like to NOT proliferate the number of views on a page. However for a single page view, if the page is only one view plus maybe a view attachment, I'd go with Views.
What about MySQL Views instead of Drupal Views or Entity Field Query API?
Compared to using the Views UI, the work I did above with the Entity Field Query API was about as tedious as working with Drupal can be. I wondered if it would be even faster if I took each of the "views" I had just done, wrote the same query in straight SQL, turned that into a MySQL view, and used db_query to load it. I would say it took about an hour to write those four EFQ "views" into SQL and replace the EFQ stuff with db_query.
The resulting PHP code was drastically cleaner than the EFQ code. The query logic was no longer in the code but in the database. It's a matter of opinion whether that is good or bad. Certainly the SQL could have been left in the code as $sql = "...". I was more curious if it would cause the page to render faster than even EFQ. When I ran the benchmark, I was surprised to see that it was only very slightly faster than EFQ, not enough to think about, and within random chance.