mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-17 19:13:16 +08:00
The timescale clustering code so far has been written referring to the remote databases as 'servers'. This terminology is a bit overloaded, and in particular we don't enforce any network topology limitations that the term 'server' would suggest. In light of this we've decided to change to use the term 'node' when referring to the different databases in a distributed database. Specifically we refer to the frontend as an 'access node' and to the backends as 'data nodes', though we may omit the access or data qualifier where it's unambiguous. As the vast bulk of the code so far has been written for the case where there was a single access node, almost all instances of 'server' were references to data nodes. This change has updated the code to rename those instances.
595 lines
21 KiB
PL/PgSQL
595 lines
21 KiB
PL/PgSQL
-- This file and its contents are licensed under the Apache License 2.0.
|
|
-- Please see the included NOTICE for copyright information and
|
|
-- LICENSE-APACHE for a copy of the license.
|
|
|
|
-- This file contains utility functions to get the relation size
|
|
-- of hypertables, chunks, and indexes on hypertables.
|
|
|
|
CREATE OR REPLACE FUNCTION _timescaledb_internal.hypertable_relation_local_size(
|
|
schema_name_in name,
|
|
table_name_in name)
|
|
RETURNS TABLE (
|
|
table_bytes bigint,
|
|
index_bytes bigint,
|
|
toast_bytes bigint,
|
|
total_bytes bigint)
|
|
LANGUAGE PLPGSQL STABLE STRICT AS
|
|
$BODY$
|
|
BEGIN
|
|
RETURN QUERY
|
|
SELECT
|
|
sub2.table_bytes,
|
|
sub2.index_bytes,
|
|
sub2.toast_bytes,
|
|
sub2.total_bytes
|
|
FROM (
|
|
SELECT
|
|
*,
|
|
sub1.total_bytes - sub1.index_bytes - COALESCE(sub1.toast_bytes, 0) AS table_bytes
|
|
FROM (
|
|
SELECT
|
|
sum(pg_total_relation_size(format('%I.%I', c.schema_name, c.table_name)))::bigint AS total_bytes,
|
|
sum(pg_indexes_size(format('%I.%I', c.schema_name, c.table_name)))::bigint AS index_bytes,
|
|
sum(pg_total_relation_size(reltoastrelid))::bigint AS toast_bytes
|
|
FROM
|
|
_timescaledb_catalog.hypertable h,
|
|
_timescaledb_catalog.chunk c,
|
|
pg_class pgc,
|
|
pg_namespace pns
|
|
WHERE
|
|
h.schema_name = schema_name_in
|
|
AND h.table_name = table_name_in
|
|
AND c.dropped = FALSE
|
|
AND c.hypertable_id = h.id
|
|
AND pgc.relname = h.table_name
|
|
AND pns.oid = pgc.relnamespace
|
|
AND pns.nspname = h.schema_name
|
|
AND relkind = 'r'
|
|
) sub1
|
|
) sub2;
|
|
END;
|
|
$BODY$;
|
|
|
|
CREATE OR REPLACE FUNCTION _timescaledb_internal.hypertable_relation_remote_size(
|
|
schema_name_in name,
|
|
table_name_in name)
|
|
RETURNS TABLE (
|
|
table_bytes bigint,
|
|
index_bytes bigint,
|
|
toast_bytes bigint,
|
|
total_bytes bigint)
|
|
LANGUAGE PLPGSQL STABLE STRICT AS
|
|
$BODY$
|
|
BEGIN
|
|
RETURN QUERY
|
|
SELECT
|
|
sum(entry.table_bytes)::bigint AS table_bytes,
|
|
sum(entry.index_bytes)::bigint AS index_bytes,
|
|
sum(entry.toast_bytes)::bigint AS toast_bytes,
|
|
sum(entry.total_bytes)::bigint AS total_bytes
|
|
FROM (
|
|
SELECT
|
|
s.node_name,
|
|
_timescaledb_internal.ping_data_node (node_name) AS node_up
|
|
FROM
|
|
_timescaledb_catalog.hypertable AS ht,
|
|
_timescaledb_catalog.hypertable_data_node AS s
|
|
WHERE
|
|
ht.schema_name = schema_name_in
|
|
AND ht.table_name = table_name_in
|
|
AND s.hypertable_id = ht.id
|
|
) AS srv
|
|
LEFT OUTER JOIN LATERAL @extschema@.data_node_hypertable_info(
|
|
CASE WHEN srv.node_up THEN
|
|
srv.node_name
|
|
ELSE
|
|
NULL
|
|
END) entry ON TRUE
|
|
WHERE
|
|
entry.table_schema = schema_name_in
|
|
AND entry.table_name = table_name_in;
|
|
END;
|
|
$BODY$;
|
|
|
|
-- Get relation size of hypertable
|
|
-- like pg_relation_size(hypertable)
|
|
-- (https://www.postgresql.org/docs/9.6/static/functions-admin.html#FUNCTIONS-ADMIN-DBSIZE)
|
|
--
|
|
-- main_table - hypertable to get size of
|
|
--
|
|
-- Returns:
|
|
-- table_bytes - Disk space used by main_table (like pg_relation_size(main_table))
|
|
-- index_bytes - Disk space used by indexes
|
|
-- toast_bytes - Disk space of toast tables
|
|
-- total_bytes - Total disk space used by the specified table, including all indexes and TOAST data
|
|
|
|
CREATE OR REPLACE FUNCTION hypertable_relation_size(
|
|
main_table REGCLASS
|
|
)
|
|
RETURNS TABLE (table_bytes BIGINT,
|
|
index_bytes BIGINT,
|
|
toast_bytes BIGINT,
|
|
total_bytes BIGINT
|
|
) LANGUAGE PLPGSQL STABLE STRICT
|
|
AS
|
|
$BODY$
|
|
DECLARE
|
|
table_name NAME;
|
|
schema_name NAME;
|
|
is_distributed BOOL;
|
|
BEGIN
|
|
SELECT relname, nspname, replication_factor > 0
|
|
INTO STRICT table_name, schema_name, is_distributed
|
|
FROM pg_class c
|
|
INNER JOIN pg_namespace n ON (n.OID = c.relnamespace)
|
|
INNER JOIN _timescaledb_catalog.hypertable ht ON (ht.schema_name = n.nspname AND ht.table_name = c.relname)
|
|
WHERE c.OID = main_table;
|
|
|
|
CASE WHEN is_distributed THEN
|
|
RETURN QUERY SELECT * FROM _timescaledb_internal.hypertable_relation_remote_size(schema_name, table_name);
|
|
ELSE
|
|
RETURN QUERY SELECT * FROM _timescaledb_internal.hypertable_relation_local_size(schema_name, table_name);
|
|
END CASE;
|
|
END;
|
|
$BODY$;
|
|
|
|
|
|
CREATE OR REPLACE FUNCTION _timescaledb_internal.range_value_to_pretty(
|
|
time_value BIGINT,
|
|
column_type REGTYPE
|
|
)
|
|
RETURNS TEXT LANGUAGE PLPGSQL STABLE AS
|
|
$BODY$
|
|
DECLARE
|
|
BEGIN
|
|
IF NOT _timescaledb_internal.dimension_is_finite(time_value) THEN
|
|
RETURN '';
|
|
END IF;
|
|
IF time_value IS NULL THEN
|
|
RETURN format('%L', NULL);
|
|
END IF;
|
|
CASE column_type
|
|
WHEN 'BIGINT'::regtype, 'INTEGER'::regtype, 'SMALLINT'::regtype THEN
|
|
RETURN format('%L', time_value); -- scale determined by user.
|
|
WHEN 'TIMESTAMP'::regtype, 'TIMESTAMPTZ'::regtype THEN
|
|
-- assume time_value is in microsec
|
|
RETURN format('%1$L', _timescaledb_internal.to_timestamp(time_value)); -- microseconds
|
|
WHEN 'DATE'::regtype THEN
|
|
RETURN format('%L', timezone('UTC',_timescaledb_internal.to_timestamp(time_value))::date);
|
|
ELSE
|
|
RETURN time_value;
|
|
END CASE;
|
|
END
|
|
$BODY$;
|
|
|
|
|
|
CREATE OR REPLACE FUNCTION _timescaledb_internal.partitioning_column_to_pretty(
|
|
d _timescaledb_catalog.dimension
|
|
)
|
|
RETURNS TEXT LANGUAGE PLPGSQL STABLE STRICT AS
|
|
$BODY$
|
|
DECLARE
|
|
BEGIN
|
|
IF d.partitioning_func IS NULL THEN
|
|
RETURN d.column_name;
|
|
ELSE
|
|
RETURN format('%I.%I(%I)', d.partitioning_func_schema, d.partitioning_func, d.column_name);
|
|
END IF;
|
|
END
|
|
$BODY$;
|
|
|
|
|
|
-- Get relation size of hypertable
|
|
-- like pg_relation_size(hypertable)
|
|
-- (https://www.postgresql.org/docs/9.6/static/functions-admin.html#FUNCTIONS-ADMIN-DBSIZE)
|
|
--
|
|
-- main_table - hypertable to get size of
|
|
--
|
|
-- Returns:
|
|
-- table_size - Pretty output of table_bytes
|
|
-- index_bytes - Pretty output of index_bytes
|
|
-- toast_bytes - Pretty output of toast_bytes
|
|
-- total_size - Pretty output of total_bytes
|
|
|
|
CREATE OR REPLACE FUNCTION hypertable_relation_size_pretty(
|
|
main_table REGCLASS
|
|
)
|
|
RETURNS TABLE (table_size TEXT,
|
|
index_size TEXT,
|
|
toast_size TEXT,
|
|
total_size TEXT) LANGUAGE PLPGSQL STABLE STRICT
|
|
AS
|
|
$BODY$
|
|
DECLARE
|
|
table_name NAME;
|
|
schema_name NAME;
|
|
BEGIN
|
|
RETURN QUERY
|
|
SELECT pg_size_pretty(table_bytes) as table,
|
|
pg_size_pretty(index_bytes) as index,
|
|
pg_size_pretty(toast_bytes) as toast,
|
|
pg_size_pretty(total_bytes) as total
|
|
FROM @extschema@.hypertable_relation_size(main_table);
|
|
|
|
END;
|
|
$BODY$;
|
|
|
|
|
|
-- Get the per-node relation size of a distributed hypertable across all nodes in a distributed database
|
|
-- like pg_relation_size(hypertable)
|
|
-- (https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADMIN-DBSIZE)
|
|
--
|
|
-- main_table - hypertable to get size of
|
|
--
|
|
-- Returns:
|
|
-- node_name - Data node hosting part of the table
|
|
-- num_chunks - Number of chunks hosted on the data node
|
|
-- table_size - Pretty output of table_bytes for the data node
|
|
-- index_bytes - Pretty output of index_bytes for the data node
|
|
-- toast_bytes - Pretty output of toast_bytes for the data node
|
|
-- total_size - Pretty output of total_bytes for the data node
|
|
|
|
CREATE OR REPLACE FUNCTION hypertable_data_node_relation_size(
|
|
main_table REGCLASS
|
|
)
|
|
RETURNS TABLE (node_name NAME,
|
|
num_chunks BIGINT,
|
|
table_size TEXT,
|
|
index_size TEXT,
|
|
toast_size TEXT,
|
|
total_size TEXT) LANGUAGE PLPGSQL STABLE STRICT
|
|
AS
|
|
$BODY$
|
|
DECLARE
|
|
local_table_name NAME;
|
|
local_schema_name NAME;
|
|
BEGIN
|
|
SELECT relname, nspname
|
|
INTO STRICT local_table_name, local_schema_name
|
|
FROM pg_class c
|
|
INNER JOIN pg_namespace n ON (n.OID = c.relnamespace)
|
|
WHERE c.OID = main_table;
|
|
|
|
IF NOT (SELECT distributed FROM timescaledb_information.hypertable ht WHERE ht.table_name = local_table_name AND ht.table_schema = local_schema_name)
|
|
THEN RAISE NOTICE 'calling hypertable_data_node_relation_size on a non-distributed hypertable';
|
|
END IF;
|
|
|
|
RETURN QUERY EXECUTE format(
|
|
$$
|
|
SELECT s.node_name as node,
|
|
size.num_chunks as chunks,
|
|
pg_size_pretty(table_bytes) as table,
|
|
pg_size_pretty(index_bytes) as index,
|
|
pg_size_pretty(toast_bytes) as toast,
|
|
pg_size_pretty(total_bytes) as total
|
|
FROM timescaledb_information.data_node s
|
|
LEFT OUTER JOIN LATERAL @extschema@.data_node_hypertable_info(s.node_name) size ON TRUE
|
|
WHERE size.table_schema = %L
|
|
AND size.table_name = %L;
|
|
$$,
|
|
local_schema_name, local_table_name);
|
|
END;
|
|
$BODY$;
|
|
|
|
-- Get relation size of the chunks of an hypertable
|
|
-- like pg_relation_size
|
|
-- (https://www.postgresql.org/docs/9.6/static/functions-admin.html#FUNCTIONS-ADMIN-DBSIZE)
|
|
--
|
|
-- main_table - hypertable to get size of
|
|
--
|
|
-- Returns:
|
|
-- chunk_id - Timescaledb id of a chunk
|
|
-- chunk_table - Table used for the chunk
|
|
-- partitioning_columns - Partitioning column names
|
|
-- partitioning_column_types - Type of partitioning columns
|
|
-- partitioning_hash_functions - Hash functions of partitioning columns
|
|
-- ranges - Partition ranges for each dimension of the chunk
|
|
-- table_bytes - Disk space used by main_table
|
|
-- index_bytes - Disk space used by indexes
|
|
-- toast_bytes - Disk space of toast tables
|
|
-- total_bytes - Disk space used in total
|
|
|
|
CREATE OR REPLACE FUNCTION chunk_relation_size(
|
|
main_table REGCLASS
|
|
)
|
|
RETURNS TABLE (chunk_id INT,
|
|
chunk_table TEXT,
|
|
partitioning_columns NAME[],
|
|
partitioning_column_types REGTYPE[],
|
|
partitioning_hash_functions TEXT[],
|
|
ranges int8range[],
|
|
table_bytes BIGINT,
|
|
index_bytes BIGINT,
|
|
toast_bytes BIGINT,
|
|
total_bytes BIGINT)
|
|
LANGUAGE PLPGSQL STABLE STRICT
|
|
AS
|
|
$BODY$
|
|
DECLARE
|
|
table_name NAME;
|
|
schema_name NAME;
|
|
BEGIN
|
|
SELECT relname, nspname
|
|
INTO STRICT table_name, schema_name
|
|
FROM pg_class c
|
|
INNER JOIN pg_namespace n ON (n.OID = c.relnamespace)
|
|
WHERE c.OID = main_table;
|
|
|
|
RETURN QUERY EXECUTE format(
|
|
$$
|
|
|
|
SELECT chunk_id,
|
|
chunk_table,
|
|
partitioning_columns,
|
|
partitioning_column_types,
|
|
partitioning_hash_functions,
|
|
ranges,
|
|
table_bytes,
|
|
index_bytes,
|
|
toast_bytes,
|
|
total_bytes
|
|
FROM (
|
|
SELECT *,
|
|
total_bytes-index_bytes-COALESCE(toast_bytes,0) AS table_bytes
|
|
FROM (
|
|
SELECT c.id as chunk_id,
|
|
format('%%I.%%I', c.schema_name, c.table_name) as chunk_table,
|
|
pg_total_relation_size(format('%%I.%%I', c.schema_name, c.table_name)) AS total_bytes,
|
|
pg_indexes_size(format('%%I.%%I', c.schema_name, c.table_name)) AS index_bytes,
|
|
pg_total_relation_size(reltoastrelid) AS toast_bytes,
|
|
array_agg(d.column_name ORDER BY d.interval_length, d.column_name ASC) as partitioning_columns,
|
|
array_agg(d.column_type ORDER BY d.interval_length, d.column_name ASC) as partitioning_column_types,
|
|
array_agg(d.partitioning_func_schema || '.' || d.partitioning_func ORDER BY d.interval_length, d.column_name ASC) as partitioning_hash_functions,
|
|
array_agg(int8range(range_start, range_end) ORDER BY d.interval_length, d.column_name ASC) as ranges
|
|
FROM
|
|
_timescaledb_catalog.hypertable h,
|
|
_timescaledb_catalog.chunk c,
|
|
_timescaledb_catalog.chunk_constraint cc,
|
|
_timescaledb_catalog.dimension d,
|
|
_timescaledb_catalog.dimension_slice ds,
|
|
pg_class pgc,
|
|
pg_namespace pns
|
|
WHERE h.schema_name = %L
|
|
AND h.table_name = %L
|
|
AND pgc.relname = c.table_name
|
|
AND pns.oid = pgc.relnamespace
|
|
AND pns.nspname = c.schema_name
|
|
AND relkind = 'r'
|
|
AND c.hypertable_id = h.id
|
|
AND c.id = cc.chunk_id
|
|
AND cc.dimension_slice_id = ds.id
|
|
AND ds.dimension_id = d.id
|
|
GROUP BY c.id, pgc.reltoastrelid, pgc.oid ORDER BY c.id
|
|
) sub1
|
|
) sub2;
|
|
$$,
|
|
schema_name, table_name);
|
|
|
|
END;
|
|
$BODY$;
|
|
|
|
-- Get relation size of the chunks of an hypertable
|
|
-- like pg_relation_size
|
|
-- (https://www.postgresql.org/docs/9.6/static/functions-admin.html#FUNCTIONS-ADMIN-DBSIZE)
|
|
--
|
|
-- main_table - hypertable to get size of
|
|
--
|
|
-- Returns:
|
|
-- chunk_id - Timescaledb id of a chunk
|
|
-- chunk_table - Table used for the chunk
|
|
-- partitioning_columns - Partitioning column names
|
|
-- partitioning_column_types - Type of partitioning columns
|
|
-- partitioning_hash_functions - Hash functions of partitioning columns
|
|
-- ranges - Partition ranges for each dimension of the chunk
|
|
-- table_size - Pretty output of table_bytes
|
|
-- index_size - Pretty output of index_bytes
|
|
-- toast_size - Pretty output of toast_bytes
|
|
-- total_size - Pretty output of total_bytes
|
|
|
|
|
|
CREATE OR REPLACE FUNCTION chunk_relation_size_pretty(
|
|
main_table REGCLASS
|
|
)
|
|
RETURNS TABLE (chunk_id INT,
|
|
chunk_table TEXT,
|
|
partitioning_columns NAME[],
|
|
partitioning_column_types REGTYPE[],
|
|
partitioning_hash_functions TEXT[],
|
|
ranges TEXT[],
|
|
table_size TEXT,
|
|
index_size TEXT,
|
|
toast_size TEXT,
|
|
total_size TEXT
|
|
)
|
|
LANGUAGE PLPGSQL STABLE STRICT
|
|
AS
|
|
$BODY$
|
|
DECLARE
|
|
table_name NAME;
|
|
schema_name NAME;
|
|
BEGIN
|
|
SELECT relname, nspname
|
|
INTO STRICT table_name, schema_name
|
|
FROM pg_class c
|
|
INNER JOIN pg_namespace n ON (n.OID = c.relnamespace)
|
|
WHERE c.OID = main_table;
|
|
|
|
RETURN QUERY EXECUTE format(
|
|
$$
|
|
|
|
SELECT chunk_id,
|
|
chunk_table,
|
|
partitioning_columns,
|
|
partitioning_column_types,
|
|
partitioning_functions,
|
|
ranges,
|
|
pg_size_pretty(table_bytes) AS table,
|
|
pg_size_pretty(index_bytes) AS index,
|
|
pg_size_pretty(toast_bytes) AS toast,
|
|
pg_size_pretty(total_bytes) AS total
|
|
FROM (
|
|
SELECT *,
|
|
total_bytes-index_bytes-COALESCE(toast_bytes,0) AS table_bytes
|
|
FROM (
|
|
SELECT c.id as chunk_id,
|
|
format('%%I.%%I', c.schema_name, c.table_name) as chunk_table,
|
|
pg_total_relation_size(format('%%I.%%I', c.schema_name, c.table_name)) AS total_bytes,
|
|
pg_indexes_size(format('%%I.%%I', c.schema_name, c.table_name)) AS index_bytes,
|
|
pg_total_relation_size(reltoastrelid) AS toast_bytes,
|
|
array_agg(d.column_name ORDER BY d.interval_length, d.column_name ASC) as partitioning_columns,
|
|
array_agg(d.column_type ORDER BY d.interval_length, d.column_name ASC) as partitioning_column_types,
|
|
array_agg(d.partitioning_func_schema || '.' || d.partitioning_func ORDER BY d.interval_length, d.column_name ASC) as partitioning_functions,
|
|
array_agg('[' || _timescaledb_internal.range_value_to_pretty(range_start, column_type) ||
|
|
',' ||
|
|
_timescaledb_internal.range_value_to_pretty(range_end, column_type) || ')' ORDER BY d.interval_length, d.column_name ASC) as ranges
|
|
FROM
|
|
_timescaledb_catalog.hypertable h,
|
|
_timescaledb_catalog.chunk c,
|
|
_timescaledb_catalog.chunk_constraint cc,
|
|
_timescaledb_catalog.dimension d,
|
|
_timescaledb_catalog.dimension_slice ds,
|
|
pg_class pgc,
|
|
pg_namespace pns
|
|
WHERE h.schema_name = %L
|
|
AND h.table_name = %L
|
|
AND pgc.relname = c.table_name
|
|
AND pns.oid = pgc.relnamespace
|
|
AND pns.nspname = c.schema_name
|
|
AND relkind = 'r'
|
|
AND c.hypertable_id = h.id
|
|
AND c.id = cc.chunk_id
|
|
AND cc.dimension_slice_id = ds.id
|
|
AND ds.dimension_id = d.id
|
|
GROUP BY c.id, pgc.reltoastrelid, pgc.oid ORDER BY c.id
|
|
) sub1
|
|
) sub2;
|
|
$$,
|
|
schema_name, table_name);
|
|
|
|
END;
|
|
$BODY$;
|
|
|
|
|
|
-- Get sizes of indexes on a hypertable
|
|
--
|
|
-- main_table - hypertable to get index sizes of
|
|
--
|
|
-- Returns:
|
|
-- index_name - index on hyper table
|
|
-- total_bytes - size of index on disk
|
|
|
|
CREATE OR REPLACE FUNCTION indexes_relation_size(
|
|
main_table REGCLASS
|
|
)
|
|
RETURNS TABLE (index_name TEXT,
|
|
total_bytes BIGINT)
|
|
LANGUAGE PLPGSQL STABLE STRICT
|
|
AS
|
|
$BODY$
|
|
<<main>>
|
|
DECLARE
|
|
table_name NAME;
|
|
schema_name NAME;
|
|
BEGIN
|
|
SELECT relname, nspname
|
|
INTO STRICT table_name, schema_name
|
|
FROM pg_class c
|
|
INNER JOIN pg_namespace n ON (n.OID = c.relnamespace)
|
|
WHERE c.OID = main_table;
|
|
|
|
RETURN QUERY
|
|
SELECT format('%I.%I', h.schema_name, ci.hypertable_index_name),
|
|
sum(pg_relation_size(c.oid))::bigint
|
|
FROM
|
|
pg_class c,
|
|
pg_namespace n,
|
|
_timescaledb_catalog.hypertable h,
|
|
_timescaledb_catalog.chunk ch,
|
|
_timescaledb_catalog.chunk_index ci
|
|
WHERE ch.schema_name = n.nspname
|
|
AND c.relnamespace = n.oid
|
|
AND c.relname = ci.index_name
|
|
AND ch.id = ci.chunk_id
|
|
AND h.id = ci.hypertable_id
|
|
AND h.schema_name = main.schema_name
|
|
AND h.table_name = main.table_name
|
|
GROUP BY h.schema_name, ci.hypertable_index_name;
|
|
END;
|
|
$BODY$;
|
|
|
|
|
|
-- Get sizes of indexes on a hypertable
|
|
--
|
|
-- main_table - hypertable to get index sizes of
|
|
--
|
|
-- Returns:
|
|
-- index_name - index on hyper table
|
|
-- total_size - pretty output of total_bytes
|
|
|
|
CREATE OR REPLACE FUNCTION indexes_relation_size_pretty(
|
|
main_table REGCLASS
|
|
)
|
|
RETURNS TABLE (index_name TEXT,
|
|
total_size TEXT) LANGUAGE PLPGSQL STABLE STRICT
|
|
AS
|
|
$BODY$
|
|
BEGIN
|
|
RETURN QUERY
|
|
SELECT s.index_name,
|
|
pg_size_pretty(s.total_bytes)
|
|
FROM @extschema@.indexes_relation_size(main_table) s;
|
|
END;
|
|
$BODY$;
|
|
|
|
|
|
-- Convenience function to return approximate row count
|
|
--
|
|
-- main_table - hypertable to get approximate row count for; if NULL, get count
|
|
-- for all hypertables
|
|
--
|
|
-- Returns:
|
|
-- schema_name - Schema name of the hypertable
|
|
-- table_name - Table name of the hypertable
|
|
-- row_estimate - Estimated number of rows according to catalog tables
|
|
CREATE OR REPLACE FUNCTION hypertable_approximate_row_count(
|
|
main_table REGCLASS = NULL
|
|
)
|
|
RETURNS TABLE (schema_name NAME,
|
|
table_name NAME,
|
|
row_estimate BIGINT
|
|
) LANGUAGE PLPGSQL VOLATILE
|
|
AS
|
|
$BODY$
|
|
<<main>>
|
|
DECLARE
|
|
table_name NAME;
|
|
schema_name NAME;
|
|
BEGIN
|
|
IF main_table IS NOT NULL THEN
|
|
SELECT relname, nspname
|
|
INTO STRICT table_name, schema_name
|
|
FROM pg_class c
|
|
INNER JOIN pg_namespace n ON (n.OID = c.relnamespace)
|
|
WHERE c.OID = main_table;
|
|
END IF;
|
|
|
|
-- Thanks to @fvannee on Github for providing the initial draft
|
|
-- of this query
|
|
RETURN QUERY
|
|
SELECT h.schema_name,
|
|
h.table_name,
|
|
row_estimate.row_estimate
|
|
FROM _timescaledb_catalog.hypertable h
|
|
CROSS JOIN LATERAL (
|
|
SELECT sum(cl.reltuples)::BIGINT AS row_estimate
|
|
FROM _timescaledb_catalog.chunk c
|
|
JOIN pg_class cl ON cl.relname = c.table_name
|
|
WHERE c.hypertable_id = h.id
|
|
GROUP BY h.schema_name, h.table_name
|
|
) row_estimate
|
|
WHERE (main.table_name IS NULL OR h.table_name = main.table_name)
|
|
AND (main.schema_name IS NULL OR h.schema_name = main.schema_name)
|
|
ORDER BY h.schema_name, h.table_name;
|
|
END
|
|
$BODY$;
|