Slow Query Log
The queries costing you the most, ranked by total time rather than mean. The 9-second report running twice a day is easy to find; the 40ms lookup running four thousand times a minute is the one saturating the database.
src/components/ui/slow-query-log.tsxAbout
From the component's own source, where it was written.
The queries costing you the most, ranked by total time.
**Total time, not mean.** The query everyone finds first is the 9-second report that runs twice a day; the one actually saturating the database is the 40ms lookup running four thousand times a minute. Ranking by mean × calls surfaces the second, which is the whole point of a slow query log and the thing a naive "slowest queries" list gets backwards.
Statements are normalised by the caller — $1 rather than a literal — so the same query with different parameters aggregates into one row instead of ten thousand.
A query with no index scan is flagged. It is the single most actionable finding here and it is invisible in the timings alone.
Install
npx astralyx-ui add slow-query-log
Usage
import { SlowQueryLog } from '@/components/ui/slow-query-log'
<SlowQueryLog queries={queries} />Composer
Change the props and the source below follows.
<SlowQueryLog queries={queries} rankByTotal={true} />Examples
Ranked by total database time
<SlowQueryLog queries={queries} />API
Generated from the source, so it cannot fall behind the code. One table per exported component, then hooks, functions and types.
SlowQueryLog
Extends Omit<ComponentProps<'div'>, 'children'>.
| Prop | Type | Default | Description |
|---|---|---|---|
| queries | SlowQuery[] | required | { id, statement, calls, meanMs, p95Ms?, rows?, seqScan?, meta? }. Statements should be normalised by the caller so the same query aggregates into one row. |
| rankByTotal | boolean | true | mean × calls. Turn it off to rank by mean, which is the ordering most tools use and the one that hides the real problem. |
| seqScanLabel | string | 'no index' | — |
| emptyLabel | string | 'No queries in this window.' | — |
| formatDuration | (ms: number) => string | defaultDuration | — |
| headers | { query?: string; calls?: string; mean?: string; total?: string } | — | — |
| label | string | 'Slow queries' | — |
Types
SlowQuery
The queries costing you the most, ranked by total time.
| Field | Type | Description |
|---|---|---|
| id | string | — |
| statement | string | Normalised statement — parameters replaced with placeholders. |
| calls | number | Executions in the window. |
| meanMs | number | Milliseconds. |
| p95Ms? | number | — |
| rows? | number | Rows returned per call, on average. |
| seqScan? | boolean | No index was used — the most actionable finding here, and invisible in the timings alone. |
| meta? | ReactNode | — |