]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commit
Improve performance of selectinload result handling by up to ~30%
authorOliver Parker <oliver.parker@gridedge.co.uk>
Wed, 17 Jun 2026 15:15:18 +0000 (11:15 -0400)
committerMichael Bayer <mike_mp@zzzcomputing.com>
Wed, 17 Jun 2026 21:50:36 +0000 (21:50 +0000)
commit89565f125f74cdb4780fb50e60a85fc615f261ed
tree31a3158ecb3026fa62f87ed007deee42570cd3e1
parenta2e79928a933ef3a55a976d07d65c2e7d8c4284c
Improve performance of selectinload result handling by up to ~30%

* in selectinloader, dont use Bundle() to represent the PK portion
* use more efficient mapper._state_ident_getter() method in selectinloader
  which pre-resolves keys and only calls upon _get_state_attr_by_column when
  an attribute is not locally present
* removed use of groupby() + lambda against Row objects in subqueryloader; converts
  to tuple and builds lists via append()

Adds tests pinning behavior of the rewritten result handling: the uselist=False multiple-rows warning, and many-to-one loads where the foreign key value matches no row or is NULL.

Benchmarked on an in-memory SQLite database (median of 30 runs, ms):

case | baseline | branch | Δ
-- | -- | -- | --
selectin_m2m | 9.747 | 6.958 | -28.6%
selectin_m2o | 13.761 | 12.538 | -8.9%
selectin_nested | 14.670 | 11.473 | -21.8%
selectin_o2m | 14.686 | 11.823 | -19.5%
selectin_o2m_few_big | 25.771 | 19.787 | -23.2%
subquery_o2m | 15.946 | 15.736 | -1.3%

Fixes: #13363
Closes: #13364
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/13364
Pull-request-sha: 3b858fc54bb28f7c44101be5b7fdc6c02dda6c66

Change-Id: I2e772c7ee9fa9e1b50026cab8c7997b861f1acda
doc/build/changelog/unreleased_21/13363.rst
lib/sqlalchemy/orm/mapper.py
lib/sqlalchemy/orm/strategies.py
test/orm/test_selectin_relations.py
test/profiles.txt