summaryrefslogtreecommitdiff
path: root/doc/build/faq/performance.rst
diff options
context:
space:
mode:
Diffstat (limited to 'doc/build/faq/performance.rst')
-rw-r--r--doc/build/faq/performance.rst160
1 files changed, 160 insertions, 0 deletions
diff --git a/doc/build/faq/performance.rst b/doc/build/faq/performance.rst
index 6e1440721..781d6c79d 100644
--- a/doc/build/faq/performance.rst
+++ b/doc/build/faq/performance.rst
@@ -8,6 +8,166 @@ Performance
:class: faq
:backlinks: none
+.. _faq_new_caching:
+
+Why is my application slow after upgrading to 1.4 and/or 2.x?
+--------------------------------------------------------------
+
+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.
+
+The caching system allows SQLAlchemy 1.4 and above to be more performant than
+SQLAlchemy 1.3 with regards to the time spent converting SQL constructs into
+strings repeatedly. However, this only works if caching is enabled for the
+dialect and SQL constructs in use; if not, string compilation is usually
+similar to that of SQLAlchemy 1.3, with a slight decrease in speed in some
+cases.
+
+There is one case however where if SQLAlchemy's new caching system has been
+disabled (for reasons below), performance for the ORM may be in fact
+significantly poorer than that of 1.3 or other prior releases which is due to
+the lack of caching within ORM lazy loaders and object refresh queries, which
+in the 1.3 and earlier releases used the now-legacy ``BakedQuery`` system. If
+an application is seeing significant (30% or higher) degradations in
+performance (measured in time for operations to complete) when switching to
+1.4, this is the likely cause of the issue, with steps to mitigate below.
+
+.. seealso::
+
+ :ref:`sql_caching` - overview of the caching system
+
+ :ref:`caching_caveats` - additional information regarding the warnings
+ generated for elements that don't enable caching.
+
+Step one - turn on SQL logging and confirm whether or not caching is working
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Here, we want to use the technique described at
+:ref:`engine logging <sql_caching_logging>`, looking for statements with the
+``[no key]`` indicator or even ``[dialect does not support caching]``.
+The indicators we would see for SQL statements that are successfully participating
+in the caching system would be indicating ``[generated in Xs]`` when
+statements are invoked for the first time and then
+``[cached since Xs ago]`` for the vast majority of statements subsequent.
+If ``[no key]`` is prevalent in particular for SELECT statements, or
+if caching is disabled entirely due to ``[dialect does not support caching]``,
+this can be the cause of significant performance degradation.
+
+.. seealso::
+
+ :ref:`sql_caching_logging`
+
+
+Step two - identify what constructs are blocking caching from being enabled
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Assuming statements are not being cached, there should be warnings emitted
+early in the application's log (SQLAlchemy 1.4.28 and above only) indicating
+dialects, :class:`.TypeEngine` objects, and SQL constructs that are not
+participating in caching.
+
+For user defined datatypes such as those which extend :class:`_types.TypeDecorator`
+and :class:`_types.UserDefinedType`, the warnings will look like::
+
+ sqlalchemy.ext.SAWarning: MyType will not produce a cache key because the
+ ``cache_ok`` attribute is not set to True. This can have significant
+ performance implications including some performance degradations in
+ comparison to prior SQLAlchemy versions. Set this attribute to True if this
+ type object's state is safe to use in a cache key, or False to disable this
+ warning.
+
+For custom and third party SQL elements, such as those constructed using
+the techniques described at :ref:`sqlalchemy.ext.compiler_toplevel`, these
+warnings will look like::
+
+ sqlalchemy.exc.SAWarning: Class MyClass will not make use of SQL
+ compilation caching as it does not set the 'inherit_cache' attribute to
+ ``True``. This can have significant performance implications including some
+ performance degradations in comparison to prior SQLAlchemy versions. Set
+ this attribute to True if this object can make use of the cache key
+ generated by the superclass. Alternatively, this attribute may be set to
+ False which will disable this warning.
+
+For custom and third party dialects which make use of the :class:`.Dialect`
+class hierarchy, the warnings will look like::
+
+ sqlalchemy.exc.SAWarning: Dialect database:driver will not make use of SQL
+ compilation caching as it does not set the 'supports_statement_cache'
+ attribute to ``True``. This can have significant performance implications
+ including some performance degradations in comparison to prior SQLAlchemy
+ versions. Dialect maintainers should seek to set this attribute to True
+ after appropriate development and testing for SQLAlchemy 1.4 caching
+ support. Alternatively, this attribute may be set to False which will
+ disable this warning.
+
+
+Step three - enable caching for the given objects and/or seek alternatives
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Steps to mitigate the lack of caching include:
+
+* Review and set :attr:`.ExternalType.cache_ok` to ``True`` for all custom types
+ which extend from :class:`_types.TypeDecorator`,
+ :class:`_types.UserDefinedType`, as well as subclasses of these such as
+ :class:`_types.PickleType`. Set this **only** if the custom type does not
+ include any additional state attributes which affect how it renders SQL::
+
+ class MyCustomType(TypeDecorator):
+ cache_ok = True
+ impl = String
+
+ If the types in use are from a third-party library, consult with the
+ maintainers of that library so that it may be adjusted and released.
+
+ .. seealso::
+
+ :attr:`.ExternalType.cache_ok` - background on requirements to enable
+ caching for custom datatypes.
+
+* Make sure third party dialects set :attr:`.Dialect.supports_statement_cache`
+ to ``True``. What this indicates is that the maintainers of a third party
+ dialect have made sure their dialect works with SQLAlchemy 1.4 or greater,
+ and that their dialect doesn't include any compilation features which may get
+ in the way of caching. As there are some common compilation patterns which
+ can in fact interfere with caching, it's important that dialect maintainers
+ check and test this carefully, adjusting for any of the legacy patterns
+ which won't work with caching.
+
+ .. seealso::
+
+ :ref:`engine_thirdparty_caching` - background and examples for third-party
+ dialects to participate in SQL statement caching.
+
+* Custom SQL classes, including all DQL / DML constructs one might create
+ using the :ref:`sqlalchemy.ext.compiler_toplevel`, as well as ad-hoc
+ subclasses of objects such as :class:`_schema.Column` or
+ :class:`_schema.Table`. The :attr:`.HasCacheKey.inherit_cache` attribute
+ may be set to ``True`` for trivial subclasses, which do not contain any
+ subclass-specific state information which affects the SQL compilation.
+
+ .. seealso::
+
+ :ref:`compilerext_caching` - guidelines for applying the
+ :attr:`.HasCacheKey.inherit_cache` attribute.
+
+
+.. seealso::
+
+ :ref:`sql_caching` - caching system overview
+
+ :ref:`caching_caveats` - background on warnings emitted when caching
+ is not enabled for specific constructs and/or dialects.
+
+
.. _faq_how_to_profile:
How can I profile a SQLAlchemy powered application?