diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2021-12-03 14:04:05 -0500 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2021-12-06 18:27:19 -0500 |
| commit | 22deafe15289d2be55682e1632016004b02b62c0 (patch) | |
| tree | 5b521531418aebd4e293f848ebe4accbbd9bc5bc /doc/build/errors.rst | |
| parent | e88dc004e6bcd1418cb8eb811d0aa580c2a44b8f (diff) | |
| download | sqlalchemy-22deafe15289d2be55682e1632016004b02b62c0.tar.gz | |
Warn when caching is disabled / document
This patch adds new warnings for all elements that
don't indicate their caching behavior, including user-defined
ClauseElement subclasses and third party dialects.
it additionally adds new documentation to discuss an apparent
performance degradation in 1.4 when caching is disabled as a
result in the significant expense incurred by ORM
lazy loaders, which in 1.3 used BakedQuery so were actually
cached.
As a result of adding the warnings, a fair degree of
lesser used SQL expression objects identified that they did not
define caching behavior so would have been producing
``[no key]``, including PostgreSQL constructs ``hstore``
and ``array``. These have been amended to use inherit
cache where appropriate. "on conflict" constructs in
PostgreSQL, MySQL, SQLite still explicitly don't generate
a cache key at this time.
The change also adds a test for all constructs via
assert_compile() to assert they will not generate cache
warnings.
Fixes: #7394
Change-Id: I85958affbb99bfad0f5efa21bc8f2a95e7e46981
Diffstat (limited to 'doc/build/errors.rst')
| -rw-r--r-- | doc/build/errors.rst | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/doc/build/errors.rst b/doc/build/errors.rst index 297bcf6f2..4845963b0 100644 --- a/doc/build/errors.rst +++ b/doc/build/errors.rst @@ -122,6 +122,95 @@ this warning is at :ref:`deprecation_20_mode`. :ref:`deprecation_20_mode` - specific guidelines on how to use "2.0 deprecations mode" in SQLAlchemy 1.4. +.. _error_cprf: +.. _caching_caveats: + +Object will not produce a cache key, Performance Implications +-------------------------------------------------------------- + +SQLAlchemy as of version 1.4 includes a +:ref:`SQL compilation caching facility <sql_caching>` which will allow +Core and ORM SQL constructs to cache their stringified form, along with other +structural information used to fetch results from the statement, allowing the +relatively expensive string compilation process to be skipped when another +structurally equivalent construct is next used. This system +relies upon functionality that is implemented for all SQL constructs, including +objects such as :class:`_schema.Column`, +:func:`_sql.select`, and :class:`_types.TypeEngine` objects, to produce a +**cache key** which fully represents their state to the degree that it affects +the SQL compilation process. + +If the warnings in question refer to widely used objects such as +:class:`_schema.Column` objects, and are shown to be affecting the majority of +SQL constructs being emitted (using the estimation techniques described at +:ref:`sql_caching_logging`) such that caching is generally not enabled for an +application, this will negatively impact performance and can in some cases +effectively produce a **performance degradation** compared to prior SQLAlchemy +versions. The FAQ at :ref:`faq_new_caching` covers this in additional detail. + +Caching disables itself if there's any doubt +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Caching relies on being able to generate a cache key that accurately represents +the **complete structure** of a statement in a **consistent** fashion. If a particular +SQL construct (or type) does not have the appropriate directives in place which +allow it to generate a proper cache key, then caching cannot be safely enabled: + +* The cache key must represent the **complete structure**: If the usage of two + separate instances of that construct may result in different SQL being + rendered, caching the SQL against the first instance of the element using a + cache key that does not capture the distinct differences between the first and + second elements will result in incorrect SQL being cached and rendered for the + second instance. + +* The cache key must be **consistent**: If a construct represents state that + changes every time, such as a literal value, producing unique SQL for every + instance of it, this construct is also not safe to cache, as repeated use of + the construct will quickly fill up the statement cache with unique SQL strings + that will likely not be used again, defeating the purpose of the cache. + +For the above two reasons, SQLAlchemy's caching system is **extremely +conservative** about deciding to cache the SQL corresponding to an object. + +Assertion attributes for caching +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The warning is emitted based on the criteria below. For further detail on +each, see the section :ref:`faq_new_caching`. + +* The :class:`.Dialect` itself (i.e. the module that is specified by the + first part of the URL we pass to :func:`_sa.create_engine`, like + ``postgresql+psycopg2://``), must indicate it has been reviewed and tested + to support caching correctly, which is indicated by the + :attr:`.Dialect.supports_statement_cache` attribute being set to ``True``. + When using third party dialects, consult with the maintainers of the dialect + so that they may follow the :ref:`steps to ensure caching may be enabled + <engine_thirdparty_caching>` in their dialect and publish a new release. + +* Third party or user defined types that inherit from either + :class:`.TypeDecorator` or :class:`.UserDefinedType` must include the + :attr:`.ExternalType.cache_ok` attribute in their definition, including for + all derived subclasses, following the guidelines described in the docstring + for :attr:`.ExternalType.cache_ok`. As before, if these datatypes are + imported from third party libraries, consult with the maintainers of that + library so that they may provide the necessary changes to their library and + publish a new release. + +* Third party or user defined SQL constructs that subclass from classes such + as :class:`.ClauseElement`, :class:`_schema.Column`, :class:`_dml.Insert` + etc, including simple subclasses as well as those which are designed to + work with the :ref:`sqlalchemy.ext.compiler_toplevel`, should normally + include the :attr:`.HasCacheKey.inherit_cache` attribute set to ``True`` + or ``False`` based on the design of the construct, following the guidelines + described at :ref:`compilerext_caching`. + +.. seealso:: + + :ref:`sql_caching_logging` - background on observing cache behavior + and efficiency + + :ref:`faq_new_caching` - in the :ref:`faq_toplevel` section + .. _error_s9r1: Object is being merged into a Session along the backref cascade |
