diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2021-06-08 15:43:13 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2021-06-09 10:01:13 -0400 |
| commit | b8ff111975be2b8d2e370f51168e39c7fae44e92 (patch) | |
| tree | 2bc531c9be05614605d8b3ef527513c37d8044bd /lib/sqlalchemy/orm | |
| parent | 5a0c700bb96bf2d80cfbf03f5ddfa97964987e4e (diff) | |
| download | sqlalchemy-b8ff111975be2b8d2e370f51168e39c7fae44e92.tar.gz | |
simplify relationship caching options
Clarified the current purpose of the
:paramref:`_orm.relationship.bake_queries` flag, which in 1.4 is to enable
or disable "lambda caching" of statements within the "lazyload" and
"selectinload" loader strategies; this is separate from the more
foundational SQL query cache that is used for most statements.
Additionally, the lazy loader no longer uses its own cache for many-to-one
SQL queries, which was an implementation quirk that doesn't exist for any
other loader scenario. Finally, the "lru cache" warning that the lazyloader
and selectinloader strategies could emit when handling a wide array of
class/relationship combinations has been removed; based on analysis of some
end-user cases, this warning doesn't suggest any significant issue. While
setting ``bake_queries=False`` for such a relationship will remove this
cache from being used, there's no particular performance gain in this case
as using no caching vs. using a cache that needs to refresh often likely
still wins out on the caching being used side.
Fixes: #6072
Fixes: #6487
Change-Id: Ida61f09b837d3acdafa07344d7d747d7f3ab226a
Diffstat (limited to 'lib/sqlalchemy/orm')
| -rw-r--r-- | lib/sqlalchemy/orm/relationships.py | 26 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/strategies.py | 38 |
2 files changed, 28 insertions, 36 deletions
diff --git a/lib/sqlalchemy/orm/relationships.py b/lib/sqlalchemy/orm/relationships.py index 2d1ed6ced..89cc37de5 100644 --- a/lib/sqlalchemy/orm/relationships.py +++ b/lib/sqlalchemy/orm/relationships.py @@ -364,20 +364,20 @@ class RelationshipProperty(StrategizedProperty): :ref:`error_qzyx` - usage example :param bake_queries=True: - Use the :class:`.BakedQuery` cache to cache the construction of SQL - used in lazy loads. True by default. Set to False if the - join condition of the relationship has unusual features that - might not respond well to statement caching. - - .. versionchanged:: 1.2 - "Baked" loading is the default implementation for the "select", - a.k.a. "lazy" loading strategy for relationships. - - .. versionadded:: 1.0.0 - - .. seealso:: + Enable :ref:`lambda caching <engine_lambda_caching>`_ for loader + strategies, if applicable, which adds a performance gain to the + construction of SQL constructs used by loader strategies, in addition + to the usual SQL statement caching used throughout SQLAlchemy. This + parameter currently applies only to the "lazy" and "selectin" loader + strategies. There is generally no reason to set this parameter to + False. - :ref:`baked_toplevel` + .. versionchanged:: 1.4 Relationship loaders no longer use the + previous "baked query" system of query caching. The "lazy" + and "selectin" loaders make use of the "lambda cache" system + for the construction of SQL constructs, + as well as the usual SQL caching system that is throughout + SQLAlchemy as of the 1.4 series. :param cascade: A comma-separated list of cascade rules which determines how diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py index dca45730c..4a8ebaabb 100644 --- a/lib/sqlalchemy/orm/strategies.py +++ b/lib/sqlalchemy/orm/strategies.py @@ -547,9 +547,6 @@ class AbstractRelationshipLoader(LoaderStrategy): self.target = self.parent_property.target self.uselist = self.parent_property.uselist - def _size_alert(self, lru_cache): - util.warn("LRU cache size alert for loader strategy: %s" % self) - @log.class_logger @relationships.RelationshipProperty.strategy_for(do_nothing=True) @@ -630,7 +627,7 @@ class LazyLoader(AbstractRelationshipLoader, util.MemoizedSlots): "_simple_lazy_clause", "_raise_always", "_raise_on_sql", - "_query_cache", + "_lambda_cache", ) def __init__(self, parent, strategy_key): @@ -899,12 +896,12 @@ class LazyLoader(AbstractRelationshipLoader, util.MemoizedSlots): for pk in self.mapper.primary_key ] - def _memoized_attr__query_cache(self): - # cache is per lazy loader; stores not only cached SQL but also + def _memoized_attr__lambda_cache(self): + # cache is per lazy loader, and is used for caching of # sqlalchemy.sql.lambdas.AnalyzedCode and # sqlalchemy.sql.lambdas.AnalyzedFunction objects which are generated # from the StatementLambda used. - return util.LRUCache(30, size_alert=self._size_alert) + return util.LRUCache(30) @util.preload_module("sqlalchemy.orm.strategy_options") def _emit_lazyload( @@ -923,7 +920,7 @@ class LazyLoader(AbstractRelationshipLoader, util.MemoizedSlots): .set_label_style(LABEL_STYLE_TABLENAME_PLUS_COL) ._set_compile_options(ORMCompileState.default_compile_options), global_track_bound_values=False, - lambda_cache=self._query_cache, + lambda_cache=self._lambda_cache, track_on=(self,), ) @@ -979,11 +976,7 @@ class LazyLoader(AbstractRelationshipLoader, util.MemoizedSlots): self._invoke_raise_load(state, passive, "raise_on_sql") return loading.load_on_pk_identity( - session, - stmt, - primary_key_identity, - load_options=load_options, - execution_options={"compiled_cache": self._query_cache}, + session, stmt, primary_key_identity, load_options=load_options ) if self._order_by: @@ -1018,8 +1011,6 @@ class LazyLoader(AbstractRelationshipLoader, util.MemoizedSlots): execution_options = { "_sa_orm_load_options": load_options, } - if not self.parent_property.bake_queries: - execution_options["compiled_cache"] = None if self.key in state.dict: return attributes.ATTR_WAS_SET @@ -1592,10 +1583,7 @@ class SubqueryLoader(PostLoader): q = self.subq assert q.session is None - if "compiled_cache" in self.execution_options: - q = q.execution_options( - compiled_cache=self.execution_options["compiled_cache"] - ) + q = q.with_session(self.session) if self.load_options._populate_existing: @@ -2626,7 +2614,7 @@ class SelectInLoader(PostLoader, util.MemoizedSlots): "_parent_alias", "_query_info", "_fallback_query_info", - "_query_cache", + "_lambda_cache", ) query_info = collections.namedtuple( @@ -2730,8 +2718,12 @@ class SelectInLoader(PostLoader, util.MemoizedSlots): (("lazy", "select"),) ).init_class_attribute(mapper) - def _memoized_attr__query_cache(self): - return util.LRUCache(30, size_alert=self._size_alert) + def _memoized_attr__lambda_cache(self): + # cache is per lazy loader, and is used for caching of + # sqlalchemy.sql.lambdas.AnalyzedCode and + # sqlalchemy.sql.lambdas.AnalyzedFunction objects which are generated + # from the StatementLambda used. + return util.LRUCache(30) def create_row_processor( self, @@ -2879,7 +2871,7 @@ class SelectInLoader(PostLoader, util.MemoizedSlots): "plugin_subject": effective_entity, } ), - lambda_cache=self._query_cache, + lambda_cache=self._lambda_cache, global_track_bound_values=False, track_on=(self, effective_entity) + (tuple(pk_cols),), ) |
