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