Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: exclude supabase managed schemas from inspect subcommand #2138

Merged
merged 14 commits into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions internal/db/reset/reset.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ func resetRemote(ctx context.Context, version string, config pgconn.Config, fsys
}

func ListSchemas(ctx context.Context, conn *pgx.Conn, exclude ...string) ([]string, error) {
exclude = likeEscapeSchema(exclude)
exclude = LikeEscapeSchema(exclude)
if len(exclude) == 0 {
exclude = append(exclude, "")
}
Expand All @@ -300,7 +300,7 @@ func ListSchemas(ctx context.Context, conn *pgx.Conn, exclude ...string) ([]stri
return pgxv5.CollectStrings(rows)
}

func likeEscapeSchema(schemas []string) (result []string) {
func LikeEscapeSchema(schemas []string) (result []string) {
// Treat _ as literal, * as any character
replacer := strings.NewReplacer("_", `\_`, "*", "%")
for _, sch := range schemas {
Expand Down
66 changes: 3 additions & 63 deletions internal/inspect/bloat/bloat.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,73 +8,13 @@ import (
"github.com/jackc/pgconn"
"github.com/jackc/pgx/v4"
"github.com/spf13/afero"
"github.com/supabase/cli/internal/db/reset"
"github.com/supabase/cli/internal/inspect"
"github.com/supabase/cli/internal/migration/list"
"github.com/supabase/cli/internal/utils"
"github.com/supabase/cli/internal/utils/pgxv5"
)

const QUERY = `
WITH constants AS (
SELECT current_setting('block_size')::numeric AS bs, 23 AS hdr, 4 AS ma
), bloat_info AS (
SELECT
ma,bs,schemaname,tablename,
(datawidth+(hdr+ma-(case when hdr%ma=0 THEN ma ELSE hdr%ma END)))::numeric AS datahdr,
(maxfracsum*(nullhdr+ma-(case when nullhdr%ma=0 THEN ma ELSE nullhdr%ma END))) AS nullhdr2
FROM (
SELECT
schemaname, tablename, hdr, ma, bs,
SUM((1-null_frac)*avg_width) AS datawidth,
MAX(null_frac) AS maxfracsum,
hdr+(
SELECT 1+count(*)/8
FROM pg_stats s2
WHERE null_frac<>0 AND s2.schemaname = s.schemaname AND s2.tablename = s.tablename
) AS nullhdr
FROM pg_stats s, constants
GROUP BY 1,2,3,4,5
) AS foo
), table_bloat AS (
SELECT
schemaname, tablename, cc.relpages, bs,
CEIL((cc.reltuples*((datahdr+ma-
(CASE WHEN datahdr%ma=0 THEN ma ELSE datahdr%ma END))+nullhdr2+4))/(bs-20::float)) AS otta
FROM bloat_info
JOIN pg_class cc ON cc.relname = bloat_info.tablename
JOIN pg_namespace nn ON cc.relnamespace = nn.oid AND nn.nspname = bloat_info.schemaname AND nn.nspname <> 'information_schema'
), index_bloat AS (
SELECT
schemaname, tablename, bs,
COALESCE(c2.relname,'?') AS iname, COALESCE(c2.reltuples,0) AS ituples, COALESCE(c2.relpages,0) AS ipages,
COALESCE(CEIL((c2.reltuples*(datahdr-12))/(bs-20::float)),0) AS iotta -- very rough approximation, assumes all cols
FROM bloat_info
JOIN pg_class cc ON cc.relname = bloat_info.tablename
JOIN pg_namespace nn ON cc.relnamespace = nn.oid AND nn.nspname = bloat_info.schemaname AND nn.nspname <> 'information_schema'
JOIN pg_index i ON indrelid = cc.oid
JOIN pg_class c2 ON c2.oid = i.indexrelid
)
SELECT
type, schemaname, object_name, bloat, pg_size_pretty(raw_waste) as waste
FROM
(SELECT
'table' as type,
schemaname,
tablename as object_name,
ROUND(CASE WHEN otta=0 THEN 0.0 ELSE table_bloat.relpages/otta::numeric END,1) AS bloat,
CASE WHEN relpages < otta THEN '0' ELSE (bs*(table_bloat.relpages-otta)::bigint)::bigint END AS raw_waste
FROM
table_bloat
UNION
SELECT
'index' as type,
schemaname,
tablename || '::' || iname as object_name,
ROUND(CASE WHEN iotta=0 OR ipages=0 THEN 0.0 ELSE ipages/iotta::numeric END,1) AS bloat,
CASE WHEN ipages < iotta THEN '0' ELSE (bs*(ipages-iotta))::bigint END AS raw_waste
FROM
index_bloat) bloat_summary
ORDER BY raw_waste DESC, bloat DESC`

type Result struct {
Type string
Schemaname string
Expand All @@ -88,7 +28,7 @@ func Run(ctx context.Context, config pgconn.Config, fsys afero.Fs, options ...fu
if err != nil {
return err
}
rows, err := conn.Query(ctx, QUERY)
rows, err := conn.Query(ctx, inspect.BLOAT_QUERY, reset.LikeEscapeSchema(utils.InternalSchemas))
if err != nil {
return errors.Errorf("failed to query rows: %w", err)
}
Expand Down
22 changes: 2 additions & 20 deletions internal/inspect/blocking/blocking.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,12 @@ import (
"github.com/jackc/pgconn"
"github.com/jackc/pgx/v4"
"github.com/spf13/afero"
"github.com/supabase/cli/internal/inspect"
"github.com/supabase/cli/internal/migration/list"
"github.com/supabase/cli/internal/utils"
"github.com/supabase/cli/internal/utils/pgxv5"
)

// Ref: https://github.com/heroku/heroku-pg-extras/blob/main/commands/blocking.js#L7
const QUERY = `
SELECT
bl.pid AS blocked_pid,
ka.query AS blocking_statement,
now() - ka.query_start AS blocking_duration,
kl.pid AS blocking_pid,
a.query AS blocked_statement,
now() - a.query_start AS blocked_duration
FROM pg_catalog.pg_locks bl
JOIN pg_catalog.pg_stat_activity a
ON bl.pid = a.pid
JOIN pg_catalog.pg_locks kl
JOIN pg_catalog.pg_stat_activity ka
ON kl.pid = ka.pid
ON bl.transactionid = kl.transactionid AND bl.pid != kl.pid
WHERE NOT bl.granted
`

type Result struct {
Blocked_pid string
Blocking_statement string
Expand All @@ -47,7 +29,7 @@ func Run(ctx context.Context, config pgconn.Config, fsys afero.Fs, options ...fu
if err != nil {
return err
}
rows, err := conn.Query(ctx, QUERY)
rows, err := conn.Query(ctx, inspect.BLOCKING_QUERY)
if err != nil {
return errors.Errorf("failed to query rows: %w", err)
}
Expand Down
30 changes: 14 additions & 16 deletions internal/inspect/cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,12 @@ import (
"github.com/jackc/pgconn"
"github.com/jackc/pgx/v4"
"github.com/spf13/afero"
"github.com/supabase/cli/internal/inspect"
"github.com/supabase/cli/internal/migration/list"
"github.com/supabase/cli/internal/utils"
"github.com/supabase/cli/internal/utils/pgxv5"
)

// Ref: https://github.com/heroku/heroku-pg-extras/blob/main/commands/cache_hit.js#L7
const QUERY = `
SELECT
'index hit rate' AS name,
(sum(idx_blks_hit)) / nullif(sum(idx_blks_hit + idx_blks_read),0) AS ratio
FROM pg_statio_user_indexes
UNION ALL
SELECT
'table hit rate' AS name,
sum(heap_blks_hit) / nullif(sum(heap_blks_hit) + sum(heap_blks_read),0) AS ratio
FROM pg_statio_user_tables;
`

type Result struct {
Name string
Ratio float64
Expand All @@ -36,7 +24,7 @@ func Run(ctx context.Context, config pgconn.Config, fsys afero.Fs, options ...fu
if err != nil {
return err
}
rows, err := conn.Query(ctx, QUERY)
rows, err := conn.Query(ctx, inspect.CACHE_QUERY)
if err != nil {
return errors.Errorf("failed to query rows: %w", err)
}
Expand All @@ -45,9 +33,19 @@ func Run(ctx context.Context, config pgconn.Config, fsys afero.Fs, options ...fu
return err
}
// TODO: implement a markdown table marshaller
table := "|Name|Ratio|\n|-|-|\n"
table := "|Name|Ratio|OK?|Explanation|\n|-|-|-|-|\n"
for _, r := range result {
table += fmt.Sprintf("|`%s`|`%.6f`|\n", r.Name, r.Ratio)
ok := "Yup!"
if r.Ratio < 0.94 {
ok = "Maybe not..."
}
var explanation string
if r.Name == "index hit rate" {
explanation = "This is the ratio of index hits to index scans. If this ratio is low, it means that the database is not using indexes effectively. Check the `index-usage` command for more info."
} else if r.Name == "table hit rate" {
explanation = "This is the ratio of table hits to table scans. If this ratio is low, it means that your queries are not finding the data effectively. Check your query performance and it might be worth increasing your compute."
}
table += fmt.Sprintf("|`%s`|`%.6f`|`%s`|`%s`|\n", r.Name, r.Ratio, ok, explanation)
}
return list.RenderTable(table)
}
15 changes: 2 additions & 13 deletions internal/inspect/calls/calls.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,12 @@ import (
"github.com/jackc/pgconn"
"github.com/jackc/pgx/v4"
"github.com/spf13/afero"
"github.com/supabase/cli/internal/inspect"
"github.com/supabase/cli/internal/migration/list"
"github.com/supabase/cli/internal/utils"
"github.com/supabase/cli/internal/utils/pgxv5"
)

const QUERY = `
SELECT
query,
interval '1 millisecond' * total_exec_time AS total_exec_time,
to_char((total_exec_time/sum(total_exec_time) OVER()) * 100, 'FM90D0') || '%' AS prop_exec_time,
to_char(calls, 'FM999G999G990') AS ncalls,
interval '1 millisecond' * (blk_read_time + blk_write_time) AS sync_io_time
FROM pg_stat_statements
ORDER BY calls DESC
LIMIT 10
`

type Result struct {
Total_exec_time string
Prop_exec_time string
Expand All @@ -39,7 +28,7 @@ func Run(ctx context.Context, config pgconn.Config, fsys afero.Fs, options ...fu
if err != nil {
return err
}
rows, err := conn.Query(ctx, QUERY)
rows, err := conn.Query(ctx, inspect.CALLS_QUERY)
if err != nil {
return errors.Errorf("failed to query rows: %w", err)
}
Expand Down
15 changes: 3 additions & 12 deletions internal/inspect/index_sizes/index_sizes.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,13 @@ import (
"github.com/jackc/pgconn"
"github.com/jackc/pgx/v4"
"github.com/spf13/afero"
"github.com/supabase/cli/internal/db/reset"
"github.com/supabase/cli/internal/inspect"
"github.com/supabase/cli/internal/migration/list"
"github.com/supabase/cli/internal/utils"
"github.com/supabase/cli/internal/utils/pgxv5"
)

const QUERY = `
SELECT c.relname AS name,
pg_size_pretty(sum(c.relpages::bigint*8192)::bigint) AS size
FROM pg_class c
LEFT JOIN pg_namespace n ON (n.oid = c.relnamespace)
WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')
AND n.nspname !~ '^pg_toast'
AND c.relkind='i'
GROUP BY c.relname
ORDER BY sum(c.relpages) DESC;`

type Result struct {
Name string
Size string
Expand All @@ -34,7 +25,7 @@ func Run(ctx context.Context, config pgconn.Config, fsys afero.Fs, options ...fu
if err != nil {
return err
}
rows, err := conn.Query(ctx, QUERY)
rows, err := conn.Query(ctx, inspect.INDEX_SIZE_QUERY, reset.LikeEscapeSchema(utils.InternalSchemas))
if err != nil {
return errors.Errorf("failed to query rows: %w", err)
}
Expand Down
22 changes: 2 additions & 20 deletions internal/inspect/index_usage/index_usage.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,12 @@ import (
"github.com/jackc/pgconn"
"github.com/jackc/pgx/v4"
"github.com/spf13/afero"
"github.com/supabase/cli/internal/inspect"
"github.com/supabase/cli/internal/migration/list"
"github.com/supabase/cli/internal/utils"
"github.com/supabase/cli/internal/utils/pgxv5"
)

const QUERY = `
SELECT relname,
CASE
WHEN idx_scan IS NULL THEN 'Insufficient data'
WHEN idx_scan = 0 THEN 'Insufficient data'
ELSE (100 * idx_scan / (seq_scan + idx_scan))::text
END percent_of_times_index_used,
n_live_tup rows_in_table
FROM
pg_stat_user_tables
ORDER BY
CASE
WHEN idx_scan is null then 1
WHEN idx_scan = 0 then 1
ELSE 0
END,
n_live_tup DESC;
`

type Result struct {
Relname string
Percent_of_times_index_used string
Expand All @@ -43,7 +25,7 @@ func Run(ctx context.Context, config pgconn.Config, fsys afero.Fs, options ...fu
if err != nil {
return err
}
rows, err := conn.Query(ctx, QUERY)
rows, err := conn.Query(ctx, inspect.INDEX_USAGE_QUERY)
if err != nil {
return errors.Errorf("failed to query rows: %w", err)
}
Expand Down
18 changes: 2 additions & 16 deletions internal/inspect/locks/locks.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,12 @@ import (
"github.com/jackc/pgconn"
"github.com/jackc/pgx/v4"
"github.com/spf13/afero"
"github.com/supabase/cli/internal/inspect"
"github.com/supabase/cli/internal/migration/list"
"github.com/supabase/cli/internal/utils"
"github.com/supabase/cli/internal/utils/pgxv5"
)

const QUERY = `
SELECT
pg_stat_activity.pid,
COALESCE(pg_class.relname, 'null') AS relname,
COALESCE(pg_locks.transactionid, 'null') AS transactionid,
pg_locks.granted,
pg_stat_activity.query,
age(now(),pg_stat_activity.query_start) AS age
FROM pg_stat_activity, pg_locks LEFT OUTER JOIN pg_class ON (pg_locks.relation = pg_class.oid)
WHERE pg_stat_activity.query <> '<insufficient privilege>'
AND pg_locks.pid=pg_stat_activity.pid
AND pg_locks.mode = 'ExclusiveLock'
ORDER BY query_start;
`

type Result struct {
Pid string
Relname string
Expand All @@ -43,7 +29,7 @@ func Run(ctx context.Context, config pgconn.Config, fsys afero.Fs, options ...fu
if err != nil {
return err
}
rows, err := conn.Query(ctx, QUERY)
rows, err := conn.Query(ctx, inspect.LOCKS_QUERY)
if err != nil {
return errors.Errorf("failed to query rows: %w", err)
}
Expand Down
17 changes: 2 additions & 15 deletions internal/inspect/long_running_queries/long_running_queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,12 @@ import (
"github.com/jackc/pgconn"
"github.com/jackc/pgx/v4"
"github.com/spf13/afero"
"github.com/supabase/cli/internal/inspect"
"github.com/supabase/cli/internal/migration/list"
"github.com/supabase/cli/internal/utils"
"github.com/supabase/cli/internal/utils/pgxv5"
)

const QUERY = `
SELECT
pid,
now() - pg_stat_activity.query_start AS duration,
query AS query
FROM
pg_stat_activity
WHERE
pg_stat_activity.query <> ''::text
AND state <> 'idle'
AND now() - pg_stat_activity.query_start > interval '5 minutes'
ORDER BY
now() - pg_stat_activity.query_start DESC;`

type Result struct {
Pid string
Duration string
Expand All @@ -38,7 +25,7 @@ func Run(ctx context.Context, config pgconn.Config, fsys afero.Fs, options ...fu
if err != nil {
return err
}
rows, err := conn.Query(ctx, QUERY)
rows, err := conn.Query(ctx, inspect.LONG_RUNNING_QUERY)
if err != nil {
return errors.Errorf("failed to query rows: %w", err)
}
Expand Down
Loading