I've been trying to figure out the caching system of views as I have a very heavy query that takes a long time to load (3-4 minutes). With caching set it loads in a few seconds.

The problem is, it seems that caching is done on a per-session basis. I tested this by setting one of my smaller static views to cache for one hour, then hitting the page with that block with different browsers on different connections. The cache_views_data table got a new row for each anonymous user that loaded the view. Once there, repeated visits didn't create any new rows, and using the devel module for my admin hitting the view I could see that on subsequent visits it was using the cache.

See the attached pic, that's two anonymous users hitting the same view, creating identical sized cache with a different cid. I read somewhere that caching should be by role which makes sense, by session doesn't seem like it would do much for resource savings.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

merlinofchaos’s picture

Status: Active » Postponed (maintainer needs more info)

The following is the exact criteria used to generate the cache key:

     $key_data = array(
        'build_info' => $build_info,
        'roles' => array_keys($user->roles),
        'super-user' => $user->uid == 1, // special caching for super user.
        'language' => $GLOBALS['language'],
      );
      foreach (array('exposed_info', 'page', 'sort', 'order') as $key) {
        if (isset($_GET[$key])) {
          $key_data[$key] = $_GET[$key];
        }
      }

      $this->_results_key = $this->view->name . ':' . $this->display->id . ':results:' . md5(serialize($key_data));
    }

You can find this in the file views/plugins/views_plugin_cache.inc

If somehow the query ends up dependent upon session data, then that would indeed happen.

You might want to put some debug in that area of the code and see what's causing the cache key to turn up different.

beck24’s picture

Thanks for prompt reply and the useful info. I'll set some debugging code and let you know what I come up with.

beck24’s picture

I hadn't had a chance to debug yet as I posted that at the end of the day, but I looked at the query - the only part that could possibly be session related is the filter "published or admin" - do you know offhand if that's what I should look at?

beck24’s picture

I var_dumped $key_data on both anonymous users. Everything is identical up to this point:

Anon User 1

["language"]=> object(stdClass)#1 (11) { ["language"]=> string(2) "en" ["name"]=> string(7) "English" ["native"]=> string(7) "English" ["direction"]=> string(1) "0" ["enabled"]=> string(1) "1" ["plurals"]=> string(1) "0" ["formula"]=> string(0) "" ["domain"]=> string(0) "" ["prefix"]=> string(0) "" ["weight"]=> string(1) "0" ["javascript"]=> string(0) "" } }

Anon User 2

["language"]=> object(stdClass)#3 (11) { ["language"]=> string(2) "en" ["name"]=> string(7) "English" ["native"]=> string(7) "English" ["direction"]=> string(1) "0" ["enabled"]=> int(1) ["plurals"]=> string(1) "0" ["formula"]=> string(0) "" ["domain"]=> string(0) "" ["prefix"]=> string(0) "" ["weight"]=> string(1) "0" ["javascript"]=> string(0) "" } } 

Any idea why the language (the same language no less) would show up differently for anonymous users?

beck24’s picture

Ok, I've sorted it out.
The site is multilingual, and has the language switcher block active, and authenticated users can set a default language for their account.
For some reason there are multiple language states per language. For anonymous users, they have one setting for using the site default language when they land on the page. If at some point they switch languages with the language switcher, and switch back, they have a different setting of the same language which creates a new cache.

Authenticated users have 3 states of language:
Site default
Language Switcher
Account default

So it's not as bad as I originally thought. Caching on this system isn't per session, it's per role per language type. Which is redundant in many cases, but I can live with it.

I'm assuming this falls under "working as designed" so I'll set it as such. If in fact this isn't as designed feel free to reopen it.

Thanks for your help Merlinofchaos.

beck24’s picture

Status: Postponed (maintainer needs more info) » Closed (works as designed)
merlinofchaos’s picture

Iiiinteresting. It's encoding an object id when we serialize the language.

Ok, I think the answer is that we need to just do $language->language not the entire object.

This was a change from D6 to D7 that maybe didn't get updated in the port.

Can you modify

        'language' => $GLOBALS['language'],

Into

        'language' => $GLOBALS['language']->language,

You'll need to do it in 2 places (the result key and the output key are generated separately).

If that works for you, can you post a patch?

merlinofchaos’s picture

Status: Closed (works as designed) » Active

Let's mark this active just long enough to see if my proposed fix helps.

beck24’s picture

Yes, that makes sense, and indeed it does work.
I'll see if I can remember how to do a patch (it's been a while)

beck24’s picture

Status: Active » Patch (to be ported)
FileSize
1.1 KB

Patch attached.

dawehner’s picture

Version: 6.x-3.0-rc3 » 7.x-3.x-dev
Status: Patch (to be ported) » Fixed

This change looks fine. Thanks for the patch!

Committed this change to 7.x-3.x

@beck24
Next time set the status to "needs review" so people will see that you have posted a patch.
Patch(to be ported) is for a patch which was written against a certain version but NOT yet against another.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.