CREATE OR REPLACE FUNCTION get_yb_catalog_index_sizes()
RETURNS TABLE (
index_name text,
base_table text,
key_columns text,
include_columns text,
is_unique boolean,
logical_bytes bigint,
logical_size text
)
LANGUAGE plpgsql
AS $$
DECLARE
r record;
BEGIN
FOR r IN
SELECT
n.nspname AS schema_name,
tbl.relname AS table_name,
idx.relname AS index_name,
i.indisunique AS is_unique,
string_agg(
format('%I', a.attname),
', ' ORDER BY k.ord
) FILTER (
WHERE k.ord <= i.indnkeyatts
) AS key_columns,
string_agg(
format('%I', a.attname),
', ' ORDER BY k.ord
) FILTER (
WHERE k.ord > i.indnkeyatts
) AS include_columns,
string_agg(
format(
'COALESCE(pg_column_size(%I), 0)',
a.attname
),
' + ' ORDER BY k.ord
) AS size_expr
FROM pg_catalog.pg_index AS i
JOIN pg_catalog.pg_class AS tbl
ON tbl.oid = i.indrelid
JOIN pg_catalog.pg_class AS idx
ON idx.oid = i.indexrelid
JOIN pg_catalog.pg_namespace AS n
ON n.oid = tbl.relnamespace
CROSS JOIN LATERAL
unnest(
string_to_array(i.indkey::text, ' ')::int2[]
) WITH ORDINALITY AS k(attnum, ord)
JOIN pg_catalog.pg_attribute AS a
ON a.attrelid = tbl.oid
AND a.attnum = k.attnum
WHERE n.nspname = 'pg_catalog'
AND i.indisvalid
AND i.indislive
AND i.indexprs IS NULL
AND i.indpred IS NULL
AND k.attnum > 0
GROUP BY
n.nspname,
tbl.relname,
idx.relname,
i.indisunique,
i.indnkeyatts
LOOP
RETURN QUERY EXECUTE format(
'SELECT %L::text,
%L::text,
%L::text,
%L::text,
%L::boolean,
bytes,
pg_size_pretty(bytes)
FROM (
SELECT COALESCE(SUM(%s), 0)::bigint AS bytes
FROM %I.%I
) AS s',
r.index_name,
r.table_name,
r.key_columns,
COALESCE(r.include_columns, ''),
r.is_unique,
r.size_expr,
r.schema_name,
r.table_name
);
END LOOP;
END;
$$;