mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-10 16:05:58 +00:00
perf: index the FK columns that cascade on workspace delete (#11052)
Claude-Session: https://claude.ai/code/session_01UtSL61CGQqtLc28AT2h75d Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
5d7eed1c02
commit
9a563f6d72
@@ -0,0 +1,7 @@
|
||||
DROP INDEX IF EXISTS index_app_version_on_app_id;
|
||||
|
||||
DROP INDEX IF EXISTS index_app_script_on_app;
|
||||
|
||||
DROP INDEX IF EXISTS index_workspace_runnable_dependencies_on_app_path;
|
||||
|
||||
DROP INDEX IF EXISTS index_workspace_runnable_dependencies_on_flow_path;
|
||||
@@ -0,0 +1,32 @@
|
||||
-- The FK columns that cascade when a workspace's apps and flows are deleted. Unindexed,
|
||||
-- Postgres seq-scans the whole child table once per deleted parent row, making a workspace
|
||||
-- delete cost O(apps and flows deleted x rows in the instance). Fork deletion is where that
|
||||
-- bites: a fork clones its parent's apps, flows and entire app version history.
|
||||
--
|
||||
-- The workspace_runnable_dependencies pair are partial because the table's check constraint
|
||||
-- makes app_path and flow_path mutually exclusive, halving each index -- the cascade's
|
||||
-- equality on the path proves the predicate. The table's existing path indexes are partial on
|
||||
-- script_hash, which the cascade does not constrain, so they cannot serve it.
|
||||
--
|
||||
-- Dropped before built: a failed concurrent build leaves an invalid index that IF NOT EXISTS
|
||||
-- would accept forever, unused by the planner yet still maintained on every write.
|
||||
--
|
||||
-- No statement separators outside the statements below, comments included: the CONCURRENTLY
|
||||
-- rewrite in windmill-api/src/db.rs splits the file on them and would run comment text as SQL.
|
||||
DROP INDEX IF EXISTS index_app_version_on_app_id;
|
||||
|
||||
CREATE INDEX index_app_version_on_app_id ON app_version (app_id);
|
||||
|
||||
DROP INDEX IF EXISTS index_app_script_on_app;
|
||||
|
||||
CREATE INDEX index_app_script_on_app ON app_script (app);
|
||||
|
||||
DROP INDEX IF EXISTS index_workspace_runnable_dependencies_on_app_path;
|
||||
|
||||
CREATE INDEX index_workspace_runnable_dependencies_on_app_path
|
||||
ON workspace_runnable_dependencies (app_path, workspace_id) WHERE app_path IS NOT NULL;
|
||||
|
||||
DROP INDEX IF EXISTS index_workspace_runnable_dependencies_on_flow_path;
|
||||
|
||||
CREATE INDEX index_workspace_runnable_dependencies_on_flow_path
|
||||
ON workspace_runnable_dependencies (flow_path, workspace_id) WHERE flow_path IS NOT NULL;
|
||||
@@ -108,6 +108,9 @@ lazy_static::lazy_static! {
|
||||
(20260826214706, include_str!(
|
||||
"../../migrations/20260826214706_queue_suspended_drop_legacy_index.up.sql"
|
||||
).replace("DROP INDEX", "DROP INDEX CONCURRENTLY")),
|
||||
(20260909163047, include_str!(
|
||||
"../../migrations/20260909163047_workspace_delete_cascade_indexes.up.sql"
|
||||
).replace("CREATE INDEX", "CREATE INDEX CONCURRENTLY").replace("DROP INDEX", "DROP INDEX CONCURRENTLY")),
|
||||
].into_iter().collect();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user