Attached patch fixes up some of the excessive caching we added during D7. In our zeal to avoid mysql load, we cache even fast queries because it is faster and more reliable to fetch from memcache, mongo, etc.

The patch creates cache_get_memory() and cache_set_memory() which no-op unless an in-memory cache backend is in use. Core won't set its DB backend to in-memory but memcache and others will. Setting this flag is all they have to do to gain these advantages.

You can see the node.module hunk of the patch that only a tiny change is needed at call time. This hunk refines the persistent caching added at #898360: Cache node types such that it only happens for memcache and similar backends. Upon positive feedback, I will add similar changes in other parts of core.

I think this is a good compromise. Open to other ideas.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Status: Needs review » Needs work

The last submitted patch, 0001-Add-memory-versions-of-cache_get-and-cache_set.-Redu.patch, failed testing.

catch’s picture

Title: Remove unnecessary persistent caching of fast queries » Allow persistent caching to be selectively skipped depending on cache backend

Let's give this issue a less loaded title.

The node type caching is more than a 'fast query' exchanged for a cache_set()/get() - it also skips invocation of hook_node_type_info() and some other stuff. Whether there's a measurable improvement when using the MySQL cache backend would require benchmarks which I don't think have been done. But just because a cache_set()/get() wraps a fast query, doesn't mean that's the only thing that's being cached. For example if we'd moved all 'info/registry' hooks to an include in D7 (which we didn't do), then caching the result of hook_node_type_info() would prevent that include from being lazy loaded on every page.

Also we need a better name than in-memory to describe this. MongoDB isn't an 'in memory' cache backend - it also stores on disk. Similarly Redis is also backed by disk storage. And potentially you might want to use http://drupal.org/project/filecache for these things as well. The main point of caching stuff like this is not that it's faster than getting it from MySQL, but just to reduce overall requests to MySQL in favour of something else.

It might be better to specify a particular cache backend to skip, and then offer hook_skip_cache_backend_alter(). Core would add $skip_cache_backends = array('DrupalDatabaseCache'); - then another caching backend could come with a module that implements hook_skip_cache_backends_alter(), or custom code could do it to tweak something that's not worth caching for that site (or to remove DrupalDatabaseCache from that array). This might be useful if we sort out chaining of cache backends as well.

moshe weitzman’s picture

OK, is true that instances of this patttern often save including some code in addition to a fast query.

I'm open to a better name than in-memory. I think it is fine though given that memory is the most frequent way to make caches fast. mongo writes to memory first according to the legendary http://www.xtranormal.com/watch/6995033/mongo-db-is-web-scale. then yes it writes to disk "later".

You say that the point of this is not to read from something faster that mysql but merely to remove requests/connections to mysql. are you suggesting that mysql is sufferring from too many connections or something?

I'm not really following the skip_cache_backend stuff. Each bin uses one and only one backend. How would it help to add a notion of skipped backends? Are you thinking that bins would use multiple backends with some priority?

catch’s picture

You say that the point of this is not to read from something faster that mysql but merely to remove requests/connections to mysql. are you suggesting that mysql is sufferring from too many connections or something?

Well it depends what the bottleneck is, if you are serving pages with 2, 5, 20 second queries then the amount of queries total is unlikely to be the bottleneck.

However you can:
- optimize slow queries to use indexes
- move slow queries into mongodb + EntityFieldQuery (where they'll be fast if done right)
- potentially have a simple site that mainly serves blog posts, maybe with an apachesolr-powered related posts block, comments and not much else.

If any of the above is true, then MySQL is going to mainly be handling CUD operations and lots of small read queries (anything that's not cached at all, and cache misses).

MongoDB, ApacheSolr etc. can generally handle much higher throughput than MySQL, so even if you moved your slow MySQL operations away, it's possible that with an increase in traffic, MySQL would continue to be the bottleneck - it still has to receive the SQL, parse it, fetch results, and send them back again.

Most of these smaller queries, as opposed to search or listing queries, are not slave-safe - they need to be bang up to date all the time - so they are much better suited to caching + expiration than replication. Also, it is much, much easier to add memcache memory (or servers) than try to scale MySQL sideways via replication. Adding extra memcache bins to a cluster is almost zero work comparatively.

I'm not really following the skip_cache_backend stuff. Each bin uses one and only one backend. How would it help to add a notion of skipped backends? Are you thinking that bins would use multiple backends with some priority?

Right I've been thinking about a stack of cache backends - an obvious one would be APC + memcache. So you'd put cache_bootstrap into both, have a version in memcache, when you invalidate APC, it would fall back to memcache so that each individual server doesn't have to do a full rebuild of the same cache item (especially now that we started adding global read locks to sites while some cache items are rebuilt). If you only have one backend and you skip it, then it would be the same as a no-op.

Fabianx’s picture

#1234830: Revert cache_menu patch removal, add a $conf setting instead (was: cache_menu: huge table size) will also profit from that as then n (= number of anchestor cache_gets) could be done instead of one slow DB query.

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.2.x-dev

Drupal 8 is end-of-life as of November 17, 2021. There will not be further changes made to Drupal 8. Bugfixes are now made to the 9.3.x and higher branches only. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.15 was released on June 1st, 2022 and is the final full bugfix release for the Drupal 9.3.x series. Drupal 9.3.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.4.x-dev branch from now on, and new development or disruptive changes should be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.9 was released on December 7, 2022 and is the final full bugfix release for the Drupal 9.4.x series. Drupal 9.4.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.5.x-dev branch from now on, and new development or disruptive changes should be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

smustgrave’s picture

Issue summary: View changes
Status: Needs work » Postponed (maintainer needs more info)

Wonder if this is still relevant for D10?

catch’s picture

I think this can be closed as outdated. The example in the issue summary is already in a dedicated bin (cache_entity) and you can define a null cache backend for that if you really want to. But more than that sites wanting to optimize their cache layer should use redis or memcache instead of trying to tweak the database cache.

smustgrave’s picture

Status: Postponed (maintainer needs more info) » Closed (outdated)

Thanks @catch!