Making queries faster with TableStudio
TableStudio can measure, not just guess. Never recommend an index or a rewrite on intuition when you can prove it with the tools below. Most of them are PostgreSQL-only; on other engines use explain_query and reason from the plan.
Pick the connection first, as described in the database-workflow skill. Prefer running analysis against a database with realistic data. A near-empty development database gives misleading plans.
Find what's slow
- The user names a query or an endpoint: find the SQL it runs (from the code or the ORM's logging), then go to "Diagnose one statement".
- "Why is the database slow?" Call
slow_queries. It ranks statements by total time frompg_stat_statements. Keep each row'squery_id; the other tools accept it. If the extension isn't installed, the tool explains what enabling it involves, so pass that on rather than installing it unasked. - Broad tuning:
workload_index_advisorfinds the fewest indexes that cover the most database time, and lists existing indexes that are never used.
A health check
When the user asks what's wrong with a database, or wants a general review, change nothing and report:
database_health. Read itsunavailablelist before summarizing: an empty findings list with entries there means checks were skipped, not that everything is fine.database_overviewfor size, the biggest and busiest tables, and connection counts.schema_issues(notable) for design problems across the database.
Put the findings that matter most first, in plain language: what's wrong, what it costs if ignored, and the fix. Include each finding's verify_sql so the user can check the number, and any fix's lock_impact. Offer to put the fixes the user picks through "Ship it" below.
Diagnose one statement
optimize_querywith the SQL (andquery_idif it came fromslow_queries). For a read-only statement, passanalyze: trueso the measured checks can run. It executes once inside a rolled-back transaction. It reportsalready_fastwhen there's nothing worth doing; say so instead of inventing an improvement.- For more detail, use
explain_query(analyze: truefor reads only). Compareactual_rowswithestimated_rowson each node. A large gap means stale statistics (ANALYZEthe table), which is often the real bug rather than a missing index. - A statement with
$1, $2placeholders needs real values to plan honestly.suggest_parameter_valuesfinds them from history, live sessions and statistics.
Prove the fix
Use benchmark_query_variants (the Query Lab) before recommending anything:
- Give it the baseline SQL and the candidates as
variants: a rewrittensql,hypothetical_indexes(planned with hypopg, never built),hide_indexes, or plannersettings. Or leavevariantsout and letfind_fasterpropose its own. - It reports medians over several runs for each parameter set, and checks that every rewrite returns the same rows as the baseline.
- Only recommend a variant whose
same_rowsis yes. Prefer the variant inrecommendation. Quote the measured before and after, not percentages from intuition.
Before dropping an index (unused or duplicate), run index_what_if with it in hide. Any statement that gets more expensive, or uses the index today, would be hurt.
Ship it
Indexes and rewrites go through the normal change flow from the database-workflow skill:
- Index changes are schema changes. If the repo has a migration tool, add the index there. Otherwise propose it with
stage_migration, with the measured numbers in therationale. - On PostgreSQL, use
CREATE INDEX CONCURRENTLYfor any table that sees traffic, and don't wrap it in a transaction. - A query rewrite is a code change: edit the code that issues it, and mention the benchmark result in your summary.