Skip to content

Core: Replace per-table has_table N+1 with single get_table_names on …#2472

Open
Tschuppi81 wants to merge 4 commits into
masterfrom
fix-n1-schema-init
Open

Core: Replace per-table has_table N+1 with single get_table_names on …#2472
Tschuppi81 wants to merge 4 commits into
masterfrom
fix-n1-schema-init

Conversation

@Tschuppi81
Copy link
Copy Markdown
Contributor

@Tschuppi81 Tschuppi81 commented May 8, 2026

Core: Replace N+1 has_table queries with single get_table_names on schema init

TYPE: Performance
LINK: None

https://seantis-gmbh.sentry.io/issues/7472765445/
https://seantis-gmbh.sentry.io/issues/7357002739/
...

The fix fetches all existing table names in the schema with a single Inspector.get_table_names() call, then passes only the missing tables to create_all(..., checkfirst=False), reducing from O(n) to O(1)

…schema init

ensure_schema_exists called metadata.create_all() which uses SQLAlchemy's
has_table() to check each table individually before creating it — one
pg_catalog.pg_class query per model. With ~152 tables registered in a
typical app this produced 152 round trips on every cold schema init
(first request after a server restart).

Replace with a single Inspector.get_table_names() call to fetch all
existing table names in one query, then pass only missing tables to
create_all(..., checkfirst=False).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@codecov
Copy link
Copy Markdown

codecov Bot commented May 8, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.35%. Comparing base (51a224b) to head (6121af8).
⚠️ Report is 6 commits behind head on master.
✅ All tests successful. No failed tests found.

Additional details and impacted files
Files with missing lines Coverage Δ
src/onegov/core/orm/session_manager.py 98.92% <100.00%> (+0.01%) ⬆️

... and 1 file with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 51a224b...6121af8. Read the comment docs.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Tschuppi81 and others added 3 commits May 8, 2026 11:26
When self.bases contains duplicate or overlapping entries, tables created
in a first iteration were not reflected in existing_tables for subsequent
ones, causing DuplicateTable errors with checkfirst=False. Update
existing_tables after each create_all call to track what was just created.

Also remove an accidental duplicate Base append in test_unique_column_value_validator
that was previously masked by checkfirst=True.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Tschuppi81 Tschuppi81 requested a review from Daverball May 11, 2026 12:47
Copy link
Copy Markdown
Member

@Daverball Daverball left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like the kind of optimization SQLAlchemy should be doing itself inside Metadata.create_all(). It might be worth opening an issue on their bug tracker.

I don't know if I'm comfortable with doing this optimization in our code, especially since it only matters the first time a schema is accessed, so we don't really gain any substantial benefits during normal operation of the application. It might slightly speed up some CLI commands, but probably not to a noticeable degree, since the biggest overhead there is podman spinning up an extra instance of the onegov container and the initial loading of all the python modules.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants