From ecbb4ec8344470d5ba68ef288ebe75a5f066104e Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 15 Jun 2026 11:54:10 +0000 Subject: [PATCH] perf(db): drop two never-used indexes on storage.files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit storage.files carried 13 indexes; every INSERT/DELETE/rename maintains all of them. Two are never chosen by the planner for any query the app issues — verified statically (query text) AND empirically on a 50k-row table via EXPLAIN + pg_stat_user_indexes over the real query shapes (idx_scan = 0): - idx_files_name_search (user_id, name text_pattern_ops): file-name search is `name ILIKE '%term%'` (served by the GIN trgm index); text_pattern_ops can serve neither ILIKE, a leading-% substring, nor default-collation ORDER BY. The one exact `name = $1` lookup is `WHERE folder_id=$1 AND name=$2`, served by the UNIQUE (folder_id, name, user_id) index. - idx_files_category_order (category_order): only emitted as a derived type_order alias inside the folders⊎files UNION-ALL listing; the ORDER BY runs post-UNION, so a single-column files index can't presort it. The real listing uses idx_files_folder_id + a top-N sort. Benchmark (50k single-row inserts, all triggers active): ~6% faster (WITH: 10.46/10.71s; WITHOUT: 9.83/10.07s — every WITHOUT run beat every WITH run) plus less disk and WAL on every file mutation. No query regression: the planner never used these indexes. Reversible. idx_folders_path (path text_pattern_ops) is intentionally KEPT — it serves exact `WHERE path = $1` equality lookups. https://claude.ai/code/session_01DCszkkU11LYxMEUWr4setK --- .../20260702000000_drop_dead_file_indexes.sql | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 migrations/20260702000000_drop_dead_file_indexes.sql diff --git a/migrations/20260702000000_drop_dead_file_indexes.sql b/migrations/20260702000000_drop_dead_file_indexes.sql new file mode 100644 index 00000000..d5ff9029 --- /dev/null +++ b/migrations/20260702000000_drop_dead_file_indexes.sql @@ -0,0 +1,35 @@ +-- ════════════════════════════════════════════════════════════════════════════ +-- Drop two never-used indexes on storage.files (pure write overhead) +-- ════════════════════════════════════════════════════════════════════════════ +-- storage.files carries 13 indexes; every INSERT/DELETE and every rename +-- (UPDATE of name) must maintain all of them. Two of those indexes are never +-- chosen by the planner for any query the application issues — confirmed both +-- statically (query text) and empirically (EXPLAIN + pg_stat_user_indexes over +-- the real query shapes on a 50k-row table, idx_scan = 0 for both): +-- +-- 1. idx_files_name_search (user_id, name text_pattern_ops) +-- Every file-name search is `name ILIKE '%term%'`. A `text_pattern_ops` +-- B-tree cannot serve ILIKE (case-insensitive), a leading-`%` substring, +-- nor a default-collation `ORDER BY name` — all of those are served by +-- idx_files_name_trgm (GIN). The one exact `name = $1` lookup +-- (find_file_by_path) is `WHERE folder_id = $1 AND name = $2`, served by +-- the UNIQUE (folder_id, name, user_id) index, never by (user_id, name). +-- +-- 2. idx_files_category_order (category_order) +-- `category_order` is only ever emitted as a derived `type_order` alias +-- inside the folders⊎files UNION-ALL listing (and the favorites/recent/ +-- trash variants); the ORDER BY runs over the post-UNION result, so a +-- single-column index on storage.files cannot provide presorted output. +-- The real listing uses idx_files_folder_id + a top-N sort. +-- +-- Dropping both removes a B-tree write from every file mutation. Measured +-- ~6% faster single-row inserts (50k loop, all triggers active) with no query +-- regression (the planner never used these indexes). Reversible: recreate from +-- the definitions in 20260307000000 / 20260527000001 if a future query needs +-- a (user_id, name) prefix or a category_order leading sort. +-- +-- NOTE: the folder analog idx_folders_path (path text_pattern_ops) is KEPT — +-- it is genuinely used for exact `WHERE path = $1` equality lookups. + +DROP INDEX IF EXISTS storage.idx_files_name_search; +DROP INDEX IF EXISTS storage.idx_files_category_order;