You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[sqlalchemy-spanner]: implement get_multi_unique_constraints() to avoid N+1 INFORMATION_SCHEMA queries during reflection #18837
I determined this is the correct repository in which to report this bug.
Summary of the issue
SpannerDialect implements get_multi_columns, get_multi_pk_constraint, get_multi_foreign_keys, and get_multi_indexes, but does not implement get_multi_unique_constraints. As a result, MetaData.reflect() and Inspector._get_reflection_info() fall back to DefaultDialect.get_multi_unique_constraints(), issuing one INFORMATION_SCHEMA query per table instead of one query per schema.
Environment details
OS: Linux
Python version: 3.13
sqlalchemy-spanner version: 1.17.2 (also reproduced on main / 1.20.1 at eb8a76628adf10093959600071a18f50285c2ecf)
sqlalchemy version: 2.0.52
Problem description
SQLAlchemy 2.0's Inspector._get_reflection_info() (used by MetaData.reflect() and Inspector.reflect_table()) calls:
get_multi_columns
get_multi_pk_constraint
get_multi_foreign_keys
get_multi_indexes
get_multi_unique_constraints
Because SpannerDialect does not override get_multi_unique_constraints, SQLAlchemy's DefaultDialect.get_multi_unique_constraints loops over every table and calls SpannerDialect.get_unique_constraints(connection, table_name, schema) individually (1 query per table).
On a Spanner schema with ~125 tables, reflecting the schema via MetaData.reflect() executes 125 separate get_unique_constraints queries (taking ~15–20 seconds against Cloud Spanner or the Spanner emulator) whereas columns, PKs, FKs, and indexes only take 1 query each.
Suggested fix
Implement SpannerDialect.get_multi_unique_constraints(self, connection, schema=None, filter_names=None, scope=None, kind=None, **kw) (and have get_unique_constraints delegate to get_multi_unique_constraints(..., filter_names=[table_name]), matching get_columns, get_pk_constraint, get_foreign_keys, and get_indexes).
Activity