1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669
|
-- 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_functions.index_matches(index1 regclass, index2 regclass) RETURNS BOOLEAN
AS '@MODULE_PATHNAME@', 'ts_index_matches' LANGUAGE C STRICT IMMUTABLE;
CREATE OR REPLACE FUNCTION _timescaledb_functions.relation_size(relation REGCLASS)
RETURNS TABLE (total_size BIGINT, heap_size BIGINT, index_size BIGINT, toast_size BIGINT)
AS '@MODULE_PATHNAME@', 'ts_relation_size' LANGUAGE C VOLATILE;
CREATE OR REPLACE FUNCTION _timescaledb_functions.relation_approximate_size(relation REGCLASS)
RETURNS TABLE (total_size BIGINT, heap_size BIGINT, index_size BIGINT, toast_size BIGINT)
AS '@MODULE_PATHNAME@', 'ts_relation_approximate_size' LANGUAGE C STRICT VOLATILE;
CREATE OR REPLACE VIEW _timescaledb_internal.hypertable_chunk_local_size AS
SELECT
h.schema_name AS hypertable_schema,
h.table_name AS hypertable_name,
h.id AS hypertable_id,
c.id AS chunk_id,
c.schema_name AS chunk_schema,
c.table_name AS chunk_name,
COALESCE((relsize).total_size, 0) AS total_bytes,
COALESCE((relsize).heap_size, 0) AS heap_bytes,
COALESCE((relsize).index_size, 0) AS index_bytes,
COALESCE((relsize).toast_size, 0) AS toast_bytes,
COALESCE((relcompsize).total_size, 0) AS compressed_total_size,
COALESCE((relcompsize).heap_size, 0) AS compressed_heap_size,
COALESCE((relcompsize).index_size, 0) AS compressed_index_size,
COALESCE((relcompsize).toast_size, 0) AS compressed_toast_size
FROM
_timescaledb_catalog.hypertable h
JOIN _timescaledb_catalog.chunk c ON h.id = c.hypertable_id
AND c.dropped IS FALSE
JOIN pg_class cl ON cl.relname = c.table_name AND cl.relkind = 'r'
JOIN pg_namespace n ON n.oid = cl.relnamespace
AND n.nspname = c.schema_name
JOIN LATERAL _timescaledb_functions.relation_size(cl.oid) AS relsize ON TRUE
LEFT JOIN _timescaledb_catalog.chunk comp ON comp.id = c.compressed_chunk_id
LEFT JOIN LATERAL _timescaledb_functions.relation_size(
CASE WHEN comp.schema_name IS NOT NULL AND comp.table_name IS NOT NULL THEN
format('%I.%I', comp.schema_name, comp.table_name)::regclass
ELSE
NULL::regclass
END
) AS relcompsize ON TRUE;
GRANT SELECT ON _timescaledb_internal.hypertable_chunk_local_size TO PUBLIC;
CREATE OR REPLACE FUNCTION _timescaledb_functions.hypertable_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 SQL VOLATILE STRICT AS
$BODY$
/* get the main hypertable id and sizes */
WITH _hypertable_sizes AS (
SELECT
id,
COALESCE((relsize).total_size, 0) AS total_bytes,
COALESCE((relsize).heap_size, 0) AS heap_bytes,
COALESCE((relsize).index_size, 0) AS index_bytes,
COALESCE((relsize).toast_size, 0) AS toast_bytes,
0::BIGINT AS compressed_total_size,
0::BIGINT AS compressed_index_size,
0::BIGINT AS compressed_toast_size,
0::BIGINT AS compressed_heap_size
FROM
_timescaledb_catalog.hypertable ht
JOIN pg_class c ON relname = ht.table_name AND c.relkind = 'r'
JOIN pg_namespace n ON n.oid = c.relnamespace
AND n.nspname = ht.schema_name
JOIN LATERAL _timescaledb_functions.relation_size(c.oid) AS relsize ON TRUE
WHERE
schema_name = schema_name_in
AND table_name = table_name_in
),
/* calculate the size of the hypertable chunks */
_chunk_sizes AS (
SELECT
chunk_id,
COALESCE(ch.total_bytes, 0) AS total_bytes,
COALESCE(ch.heap_bytes, 0) AS heap_bytes,
COALESCE(ch.index_bytes, 0) AS index_bytes,
COALESCE(ch.toast_bytes, 0) AS toast_bytes,
COALESCE(ch.compressed_total_size, 0) AS compressed_total_size,
COALESCE(ch.compressed_index_size, 0) AS compressed_index_size,
COALESCE(ch.compressed_toast_size, 0) AS compressed_toast_size,
COALESCE(ch.compressed_heap_size, 0) AS compressed_heap_size
FROM
_timescaledb_internal.hypertable_chunk_local_size ch
JOIN _hypertable_sizes ht ON ht.id = ch.hypertable_id
WHERE hypertable_schema = schema_name_in
AND hypertable_name = table_name_in
)
/* calculate the SUM of the hypertable and chunk sizes */
SELECT
(SUM(heap_bytes) + SUM(compressed_heap_size))::BIGINT AS heap_bytes,
(SUM(index_bytes) + SUM(compressed_index_size))::BIGINT AS index_bytes,
(SUM(toast_bytes) + SUM(compressed_toast_size))::BIGINT AS toast_bytes,
(SUM(total_bytes) + SUM(compressed_total_size))::BIGINT AS total_bytes
FROM
(SELECT * FROM _hypertable_sizes
UNION ALL
SELECT * FROM _chunk_sizes) AS sizes;
$BODY$ SET search_path TO pg_catalog, pg_temp;
-- Get relation size of hypertable
-- like pg_relation_size(hypertable)
--
-- hypertable - hypertable to get size of
--
-- Returns:
-- table_bytes - Disk space used by hypertable (like pg_relation_size(hypertable))
-- 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 @extschema@.hypertable_detailed_size(
hypertable REGCLASS)
RETURNS TABLE (table_bytes BIGINT,
index_bytes BIGINT,
toast_bytes BIGINT,
total_bytes BIGINT,
node_name NAME)
LANGUAGE PLPGSQL VOLATILE STRICT AS
$BODY$
DECLARE
table_name NAME = NULL;
schema_name NAME = NULL;
BEGIN
SELECT relname, nspname
INTO table_name, schema_name
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 = hypertable;
IF table_name IS NULL THEN
SELECT h.schema_name, h.table_name
INTO schema_name, table_name
FROM pg_class c
INNER JOIN pg_namespace n ON (n.OID = c.relnamespace)
INNER JOIN _timescaledb_catalog.continuous_agg a ON (a.user_view_schema = n.nspname AND a.user_view_name = c.relname)
INNER JOIN _timescaledb_catalog.hypertable h ON h.id = a.mat_hypertable_id
WHERE c.OID = hypertable;
IF table_name IS NULL THEN
RETURN;
END IF;
END IF;
RETURN QUERY
SELECT *, NULL::name
FROM _timescaledb_functions.hypertable_local_size(schema_name, table_name);
END;
$BODY$ SET search_path TO pg_catalog, pg_temp;
--- returns total-bytes for a hypertable (includes table + index)
CREATE OR REPLACE FUNCTION @extschema@.hypertable_size(
hypertable REGCLASS)
RETURNS BIGINT
LANGUAGE SQL VOLATILE STRICT AS
$BODY$
SELECT total_bytes::bigint FROM @extschema@.hypertable_detailed_size(hypertable);
$BODY$ SET search_path TO pg_catalog, pg_temp;
-- Get approximate relation size of hypertable
--
-- hypertable - hypertable to get approximate size of
--
-- Returns:
-- table_bytes - Approximate disk space used by hypertable
-- index_bytes - Approximate disk space used by indexes
-- toast_bytes - Approximate disk space of toast tables
-- total_bytes - Total approximate disk space used by the specified table, including all indexes and TOAST data
CREATE OR REPLACE FUNCTION @extschema@.hypertable_approximate_detailed_size(relation REGCLASS)
RETURNS TABLE (table_bytes BIGINT, index_bytes BIGINT, toast_bytes BIGINT, total_bytes BIGINT)
AS '@MODULE_PATHNAME@', 'ts_hypertable_approximate_size' LANGUAGE C VOLATILE;
--- returns approximate total-bytes for a hypertable (includes table + index)
CREATE OR REPLACE FUNCTION @extschema@.hypertable_approximate_size(
hypertable REGCLASS)
RETURNS BIGINT
LANGUAGE SQL VOLATILE STRICT AS
$BODY$
SELECT sum(total_bytes)::bigint
FROM @extschema@.hypertable_approximate_detailed_size(hypertable);
$BODY$ SET search_path TO pg_catalog, pg_temp;
CREATE OR REPLACE FUNCTION _timescaledb_functions.chunks_local_size(
schema_name_in name,
table_name_in name)
RETURNS TABLE (
chunk_id integer,
chunk_schema NAME,
chunk_name NAME,
table_bytes bigint,
index_bytes bigint,
toast_bytes bigint,
total_bytes bigint)
LANGUAGE SQL VOLATILE STRICT AS
$BODY$
SELECT
ch.chunk_id,
ch.chunk_schema,
ch.chunk_name,
(ch.total_bytes - COALESCE( ch.index_bytes , 0 ) - COALESCE( ch.toast_bytes, 0 ) + COALESCE( ch.compressed_heap_size , 0 ))::bigint as heap_bytes,
(COALESCE( ch.index_bytes, 0 ) + COALESCE( ch.compressed_index_size , 0) )::bigint as index_bytes,
(COALESCE( ch.toast_bytes, 0 ) + COALESCE( ch.compressed_toast_size, 0 ))::bigint as toast_bytes,
(ch.total_bytes + COALESCE( ch.compressed_total_size, 0 ))::bigint as total_bytes
FROM
_timescaledb_internal.hypertable_chunk_local_size ch
WHERE
ch.hypertable_schema = schema_name_in
AND ch.hypertable_name = table_name_in;
$BODY$ SET search_path TO pg_catalog, pg_temp;
-- Get relation size of the chunks of an hypertable
-- hypertable - hypertable to get size of
--
-- Returns:
-- chunk_schema - schema name for chunk
-- chunk_name - chunk table name
-- table_bytes - Disk space used by chunk table
-- index_bytes - Disk space used by indexes
-- toast_bytes - Disk space of toast tables
-- total_bytes - Disk space used in total
-- node_name - node on which chunk lives if this is
-- a distributed hypertable.
CREATE OR REPLACE FUNCTION @extschema@.chunks_detailed_size(
hypertable REGCLASS
)
RETURNS TABLE (
chunk_schema NAME,
chunk_name NAME,
table_bytes BIGINT,
index_bytes BIGINT,
toast_bytes BIGINT,
total_bytes BIGINT,
node_name NAME)
LANGUAGE PLPGSQL VOLATILE STRICT AS
$BODY$
DECLARE
table_name NAME;
schema_name NAME;
BEGIN
SELECT relname, nspname
INTO table_name, schema_name
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 = hypertable;
IF table_name IS NULL THEN
SELECT h.schema_name, h.table_name
INTO schema_name, table_name
FROM pg_class c
INNER JOIN pg_namespace n ON (n.OID = c.relnamespace)
INNER JOIN _timescaledb_catalog.continuous_agg a ON (a.user_view_schema = n.nspname AND a.user_view_name = c.relname)
INNER JOIN _timescaledb_catalog.hypertable h ON h.id = a.mat_hypertable_id
WHERE c.OID = hypertable;
IF table_name IS NULL THEN
RETURN;
END IF;
END IF;
RETURN QUERY SELECT chl.chunk_schema, chl.chunk_name, chl.table_bytes, chl.index_bytes,
chl.toast_bytes, chl.total_bytes, NULL::NAME
FROM _timescaledb_functions.chunks_local_size(schema_name, table_name) chl;
END;
$BODY$ SET search_path TO pg_catalog, pg_temp;
---------- end of detailed size functions ------
CREATE OR REPLACE FUNCTION _timescaledb_functions.range_value_to_pretty(
time_value BIGINT,
column_type REGTYPE
)
RETURNS TEXT LANGUAGE PLPGSQL STABLE AS
$BODY$
DECLARE
BEGIN
IF NOT (time_value > (-9223372036854775808)::bigint AND
time_value < 9223372036854775807::bigint) 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_functions.to_timestamp(time_value)); -- microseconds
WHEN 'DATE'::regtype THEN
RETURN format('%L', timezone('UTC',_timescaledb_functions.to_timestamp(time_value))::date);
ELSE
RETURN time_value;
END CASE;
END
$BODY$ SET search_path TO pg_catalog, pg_temp;
-- Convenience function to return approximate row count
--
-- relation - table or hypertable to get approximate row count for
--
-- Returns:
-- Estimated number of rows according to catalog tables
CREATE OR REPLACE FUNCTION @extschema@.approximate_row_count(relation REGCLASS)
RETURNS BIGINT
LANGUAGE PLPGSQL VOLATILE STRICT AS
$BODY$
DECLARE
v_mat_ht REGCLASS = NULL;
v_name NAME = NULL;
v_schema NAME = NULL;
v_hypertable_id INTEGER;
BEGIN
-- Check if input relation is continuous aggregate view then
-- get the corresponding materialized hypertable and schema name
SELECT format('%I.%I', ht.schema_name, ht.table_name)::regclass INTO v_mat_ht
FROM pg_class c
JOIN pg_namespace n ON (n.OID = c.relnamespace)
JOIN _timescaledb_catalog.continuous_agg a ON (a.user_view_schema = n.nspname AND a.user_view_name = c.relname)
JOIN _timescaledb_catalog.hypertable ht ON (a.mat_hypertable_id = ht.id)
WHERE c.OID = relation;
IF FOUND THEN
relation = v_mat_ht;
END IF;
SELECT nspname, relname FROM pg_class c
INNER JOIN pg_namespace n ON (n.OID = c.relnamespace)
INTO v_schema, v_name
WHERE c.OID = relation;
-- for hypertables return the sum of the row counts of all chunks
SELECT id FROM _timescaledb_catalog.hypertable INTO v_hypertable_id WHERE table_name = v_name AND schema_name = v_schema;
IF FOUND THEN
RETURN (SELECT coalesce(sum(_timescaledb_functions.get_approx_row_count(format('%I.%I',schema_name,table_name))),0)
FROM _timescaledb_catalog.chunk
WHERE hypertable_id = v_hypertable_id AND NOT dropped);
END IF;
IF EXISTS (SELECT FROM pg_inherits WHERE inhparent = relation) THEN
RETURN (
SELECT _timescaledb_functions.get_approx_row_count(relation) + COALESCE(SUM(@extschema@.approximate_row_count(i.inhrelid)),0) FROM pg_inherits i
WHERE i.inhparent = relation
);
END IF;
-- Check for input relation is Plain RELATION
RETURN _timescaledb_functions.get_approx_row_count(relation);
END;
$BODY$ SET search_path TO pg_catalog, pg_temp;
CREATE OR REPLACE FUNCTION _timescaledb_functions.estimate_compressed_batch_size(relation REGCLASS)
RETURNS FLOAT8
AS '@MODULE_PATHNAME@', 'ts_estimate_compressed_batch_size' LANGUAGE C STRICT STABLE;
CREATE OR REPLACE FUNCTION _timescaledb_functions.get_approx_row_count(relation REGCLASS)
RETURNS BIGINT
LANGUAGE PLPGSQL VOLATILE STRICT AS
$BODY$
DECLARE
v_schema NAME;
v_name NAME;
v_chunk_id INTEGER;
v_oid OID;
row_count BIGINT = 0;
BEGIN
SELECT nspname, relname INTO v_schema, v_name FROM pg_class c JOIN pg_namespace n ON (n.OID = c.relnamespace) WHERE c.OID = relation;
-- we only need to check if the relation has a compressed chunk if it is a chunk
SELECT compressed_chunk_id FROM _timescaledb_catalog.chunk INTO v_chunk_id WHERE table_name = v_name AND schema_name = v_schema;
IF v_chunk_id IS NOT NULL THEN
SELECT format('%I.%I', schema_name, table_name)::regclass INTO v_oid FROM _timescaledb_catalog.chunk WHERE id = v_chunk_id;
row_count := (SELECT CASE WHEN reltuples IS NULL THEN 0 WHEN reltuples < 0 THEN 0 ELSE reltuples * _timescaledb_functions.estimate_compressed_batch_size(oid) END FROM pg_class WHERE oid = v_oid);
END IF;
row_count := COALESCE((SELECT row_count + CASE WHEN reltuples < 0 OR relkind = 'p' THEN 0 ELSE reltuples END FROM pg_class WHERE oid = relation), 0);
RETURN row_count;
END
$BODY$ SET search_path TO pg_catalog, pg_temp;
-------- stats related to compression ------
CREATE OR REPLACE VIEW _timescaledb_internal.compressed_chunk_stats AS
SELECT
srcht.schema_name AS hypertable_schema,
srcht.table_name AS hypertable_name,
srcch.schema_name AS chunk_schema,
srcch.table_name AS chunk_name,
CASE WHEN srcch.compressed_chunk_id IS NULL THEN
'Uncompressed'::text
ELSE
'Compressed'::text
END AS compression_status,
map.uncompressed_heap_size,
map.uncompressed_index_size,
map.uncompressed_toast_size,
map.uncompressed_heap_size + map.uncompressed_toast_size + map.uncompressed_index_size AS uncompressed_total_size,
map.compressed_heap_size,
map.compressed_index_size,
map.compressed_toast_size,
map.compressed_heap_size + map.compressed_toast_size + map.compressed_index_size AS compressed_total_size
FROM
_timescaledb_catalog.hypertable AS srcht
JOIN _timescaledb_catalog.chunk AS srcch ON srcht.id = srcch.hypertable_id
AND srcht.compressed_hypertable_id IS NOT NULL
AND srcch.dropped = FALSE
LEFT JOIN _timescaledb_catalog.compression_chunk_size map ON srcch.id = map.chunk_id;
GRANT SELECT ON _timescaledb_internal.compressed_chunk_stats TO PUBLIC;
CREATE OR REPLACE FUNCTION _timescaledb_functions.compressed_chunk_local_stats(schema_name_in name, table_name_in name)
RETURNS TABLE (
chunk_schema name,
chunk_name name,
compression_status text,
before_compression_table_bytes bigint,
before_compression_index_bytes bigint,
before_compression_toast_bytes bigint,
before_compression_total_bytes bigint,
after_compression_table_bytes bigint,
after_compression_index_bytes bigint,
after_compression_toast_bytes bigint,
after_compression_total_bytes bigint)
LANGUAGE SQL
STABLE STRICT
AS
$BODY$
SELECT
ch.chunk_schema,
ch.chunk_name,
ch.compression_status,
ch.uncompressed_heap_size,
ch.uncompressed_index_size,
ch.uncompressed_toast_size,
ch.uncompressed_total_size,
ch.compressed_heap_size,
ch.compressed_index_size,
ch.compressed_toast_size,
ch.compressed_total_size
FROM
_timescaledb_internal.compressed_chunk_stats ch
WHERE
ch.hypertable_schema = schema_name_in
AND ch.hypertable_name = table_name_in;
$BODY$ SET search_path TO pg_catalog, pg_temp;
-- Get per chunk compression statistics for a hypertable that has
-- compression enabled
CREATE OR REPLACE FUNCTION @extschema@.chunk_compression_stats (hypertable REGCLASS)
RETURNS TABLE (
chunk_schema name,
chunk_name name,
compression_status text,
before_compression_table_bytes bigint,
before_compression_index_bytes bigint,
before_compression_toast_bytes bigint,
before_compression_total_bytes bigint,
after_compression_table_bytes bigint,
after_compression_index_bytes bigint,
after_compression_toast_bytes bigint,
after_compression_total_bytes bigint,
node_name name)
LANGUAGE PLPGSQL
STABLE STRICT
AS $BODY$
DECLARE
table_name name;
schema_name name;
BEGIN
SELECT
relname, nspname
INTO
table_name, schema_name
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 = hypertable;
IF table_name IS NULL THEN
RETURN;
END IF;
RETURN QUERY
SELECT
*,
NULL::name
FROM
_timescaledb_functions.compressed_chunk_local_stats(schema_name, table_name);
END;
$BODY$ SET search_path TO pg_catalog, pg_temp;
CREATE OR REPLACE FUNCTION @extschema@.chunk_columnstore_stats (hypertable REGCLASS)
RETURNS TABLE (
chunk_schema name,
chunk_name name,
compression_status text,
before_compression_table_bytes bigint,
before_compression_index_bytes bigint,
before_compression_toast_bytes bigint,
before_compression_total_bytes bigint,
after_compression_table_bytes bigint,
after_compression_index_bytes bigint,
after_compression_toast_bytes bigint,
after_compression_total_bytes bigint,
node_name name)
LANGUAGE SQL
STABLE STRICT
AS 'SELECT * FROM @extschema@.chunk_compression_stats($1)'
SET search_path TO pg_catalog, pg_temp;
-- Get compression statistics for a hypertable that has
-- compression enabled
CREATE OR REPLACE FUNCTION @extschema@.hypertable_compression_stats (hypertable REGCLASS)
RETURNS TABLE (
total_chunks bigint,
number_compressed_chunks bigint,
before_compression_table_bytes bigint,
before_compression_index_bytes bigint,
before_compression_toast_bytes bigint,
before_compression_total_bytes bigint,
after_compression_table_bytes bigint,
after_compression_index_bytes bigint,
after_compression_toast_bytes bigint,
after_compression_total_bytes bigint,
node_name name)
LANGUAGE SQL
STABLE STRICT
AS
$BODY$
SELECT
count(*)::bigint AS total_chunks,
(count(*) FILTER (WHERE ch.compression_status = 'Compressed'))::bigint AS number_compressed_chunks,
sum(ch.before_compression_table_bytes)::bigint AS before_compression_table_bytes,
sum(ch.before_compression_index_bytes)::bigint AS before_compression_index_bytes,
sum(ch.before_compression_toast_bytes)::bigint AS before_compression_toast_bytes,
sum(ch.before_compression_total_bytes)::bigint AS before_compression_total_bytes,
sum(ch.after_compression_table_bytes)::bigint AS after_compression_table_bytes,
sum(ch.after_compression_index_bytes)::bigint AS after_compression_index_bytes,
sum(ch.after_compression_toast_bytes)::bigint AS after_compression_toast_bytes,
sum(ch.after_compression_total_bytes)::bigint AS after_compression_total_bytes,
ch.node_name
FROM
@extschema@.chunk_compression_stats(hypertable) ch
GROUP BY
ch.node_name;
$BODY$ SET search_path TO pg_catalog, pg_temp;
CREATE OR REPLACE FUNCTION @extschema@.hypertable_columnstore_stats (hypertable REGCLASS)
RETURNS TABLE (
total_chunks bigint,
number_compressed_chunks bigint,
before_compression_table_bytes bigint,
before_compression_index_bytes bigint,
before_compression_toast_bytes bigint,
before_compression_total_bytes bigint,
after_compression_table_bytes bigint,
after_compression_index_bytes bigint,
after_compression_toast_bytes bigint,
after_compression_total_bytes bigint,
node_name name)
LANGUAGE SQL
STABLE STRICT
AS 'SELECT * FROM @extschema@.hypertable_compression_stats($1)'
SET search_path TO pg_catalog, pg_temp;
-------------Get index size for hypertables -------
CREATE OR REPLACE FUNCTION @extschema@.hypertable_index_size(
index_name REGCLASS
)
RETURNS BIGINT
LANGUAGE SQL VOLATILE STRICT AS
$BODY$
SELECT
pg_relation_size(ht_i.indexrelid) + COALESCE(sum(pg_relation_size(ch_i.indexrelid)), 0)
FROM pg_index ht_i
LEFT JOIN pg_inherits ch on ch.inhparent = ht_i.indrelid
LEFT JOIN pg_index ch_i on ch_i.indrelid = ch.inhrelid and _timescaledb_functions.index_matches(ht_i.indexrelid, ch_i.indexrelid)
WHERE ht_i.indexrelid = index_name
GROUP BY ht_i.indexrelid;
$BODY$ SET search_path TO pg_catalog, pg_temp;
-------------End index size for hypertables -------
CREATE OR REPLACE FUNCTION _timescaledb_functions.estimate_uncompressed_size(IN regclass, OUT tuples bigint, OUT relation_size bigint, OUT index_size bigint, OUT total_size bigint)
AS $$
DECLARE
v_compressed_chunk regclass;
v_uncompressed_chunk regclass;
v_index regclass;
v_fixed_column_size integer;
v_num_varlen_columns integer;
v_tuple_header integer;
v_tuple_data integer;
v_index_header integer;
v_index_size bigint;
v_columns integer;
v_varlen_query text:= '';
v_multiplier decimal:=1.15; -- multiplier to account for page header, fill factor and alignment padding
v_index_multiplier decimal:=1.25; -- multiplier to account for page header, fill factor and alignment padding
BEGIN
v_compressed_chunk := $1;
SELECT relid INTO v_uncompressed_chunk FROM _timescaledb_catalog.compression_settings WHERE compress_relid = v_compressed_chunk;
IF NOT FOUND THEN
RETURN;
END IF;
SELECT
count(*), sum(attlen) FILTER(WHERE attlen > 0), count(*) FILTER(WHERE attlen = -1)
FROM pg_attribute
INTO v_columns, v_fixed_column_size, v_num_varlen_columns
WHERE attrelid = v_uncompressed_chunk AND attnum > 0 AND NOT attisdropped;
-- header size = MAXALIGN(Header + NullBitmap) + MAXALIGN(Data)
v_tuple_header := 23; -- Heap tuple header
v_tuple_header := v_tuple_header + ((v_columns + 7) / 8); -- Null bitmap size
v_tuple_header := v_tuple_header + 7 & ~7; -- align to 8 bytes
v_tuple_data := v_fixed_column_size; -- Fixed-length column sizes
v_tuple_data := v_tuple_data + 7 & ~7; -- align to 8 bytes
IF v_num_varlen_columns > 0 THEN
SELECT ' + (' || string_agg(format('sum(_timescaledb_functions.compressed_data_column_size(%I,NULL::%s))', attname, pg_catalog.format_type(atttypid, atttypmod)), ' + ') || ')' FROM pg_attribute INTO v_varlen_query WHERE attrelid = v_uncompressed_chunk AND attnum > 0 AND NOT attisdropped AND attlen = -1;
END IF;
EXECUTE format('SELECT sum(_ts_meta_count) FROM %s', v_compressed_chunk) INTO tuples;
-- we can optimize the following query if all columns are fixed size
EXECUTE format('SELECT ((%s * (%s + %s)) %s) * %s FROM %s', tuples, v_tuple_header, v_tuple_data, v_varlen_query, v_multiplier, v_compressed_chunk) INTO relation_size;
index_size := 0;
FOR v_index, v_varlen_query, v_columns IN
SELECT
i.indexrelid::regclass,
(SELECT ' + (' || string_agg(format('sum(_timescaledb_functions.compressed_data_column_size(%I,NULL::%s))', attname, pg_catalog.format_type(atttypid, atttypmod)), ' + ' ORDER BY attnum) || ')' FROM pg_attribute att WHERE att.attrelid=i.indrelid AND attnum =ANY(i.indkey)),
array_length(i.indkey,1) FROM pg_index i
WHERE i.indrelid = v_uncompressed_chunk
LOOP
v_index_header := 8; -- Index tuple header
-- v_compressed_chunk is a regclass, which will be properly escaped when cast to `text`
EXECUTE format('SELECT ((%s * %s) %s) * %s FROM %s', tuples, v_index_header, v_varlen_query, v_index_multiplier, v_compressed_chunk) INTO v_index_size;
index_size := index_size + v_index_size;
END LOOP;
total_size := relation_size + index_size;
END
$$ LANGUAGE plpgsql SET search_path TO pg_catalog, pg_temp;
|