|
| 1 | +/* gp_relaccess_stats--1.1.sql */ |
| 2 | + |
| 3 | +-- complain if script is sourced in psql, rather than via CREATE EXTENSION |
| 4 | +\echo Use "CREATE EXTENSION gp_relaccess_stats" to load this file. \quit |
| 5 | + |
| 6 | +CREATE SCHEMA IF NOT EXISTS relaccess; |
| 7 | + |
| 8 | +CREATE TABLE relaccess.relaccess_stats ( |
| 9 | + relid Oid, |
| 10 | + relname Name, |
| 11 | + last_reader_id Oid, |
| 12 | + last_writer_id Oid, |
| 13 | + last_read timestamptz, |
| 14 | + last_write timestamptz, |
| 15 | + n_select_queries int8, |
| 16 | + n_insert_queries int8, |
| 17 | + n_update_queries int8, |
| 18 | + n_delete_queries int8, |
| 19 | + n_truncate_queries int8 |
| 20 | +) DISTRIBUTED BY (relid); |
| 21 | + |
| 22 | +CREATE FUNCTION relaccess.relaccess_stats_dump() |
| 23 | +RETURNS SETOF void |
| 24 | +AS 'MODULE_PATHNAME', 'relaccess_stats_dump' |
| 25 | +LANGUAGE C VOLATILE EXECUTE ON MASTER; |
| 26 | + |
| 27 | +CREATE FUNCTION relaccess.relaccess_stats_update() |
| 28 | +RETURNS SETOF void |
| 29 | +AS 'MODULE_PATHNAME', 'relaccess_stats_update' |
| 30 | +LANGUAGE C VOLATILE EXECUTE ON MASTER; |
| 31 | + |
| 32 | +CREATE FUNCTION relaccess.relaccess_stats_fillfactor() |
| 33 | +RETURNS SETOF INT2 |
| 34 | +AS 'MODULE_PATHNAME', 'relaccess_stats_fillfactor' |
| 35 | +LANGUAGE C VOLATILE EXECUTE ON MASTER; |
| 36 | + |
| 37 | +CREATE FUNCTION relaccess.__get_db_stats_from_dump() |
| 38 | +RETURNS SETOF relaccess.relaccess_stats |
| 39 | +AS 'MODULE_PATHNAME', 'relaccess_stats_from_dump' |
| 40 | +LANGUAGE C VOLATILE EXECUTE ON MASTER; |
| 41 | + |
| 42 | +CREATE FUNCTION relaccess.__relaccess_upsert_from_dump_file() RETURNS VOID |
| 43 | +LANGUAGE plpgsql VOLATILE AS |
| 44 | +$func$ |
| 45 | +BEGIN |
| 46 | + EXECUTE 'DROP TABLE IF EXISTS relaccess_stats_tmp'; |
| 47 | + EXECUTE 'CREATE TEMP TABLE relaccess_stats_tmp (LIKE relaccess.relaccess_stats) distributed by (relid)'; |
| 48 | + EXECUTE 'DROP TABLE IF EXISTS relaccess_stats_tmp_aggregated'; |
| 49 | + EXECUTE 'CREATE TEMP TABLE relaccess_stats_tmp_aggregated (LIKE relaccess.relaccess_stats) distributed by (relid)'; |
| 50 | + EXECUTE 'INSERT INTO relaccess_stats_tmp SELECT * FROM relaccess.__get_db_stats_from_dump()'; |
| 51 | + EXECUTE 'WITH aggregated_wo_relname_and_user AS ( |
| 52 | + SELECT relid, max(last_read) AS last_read, max(last_write) AS last_write, sum(n_select_queries) AS n_select_queries, |
| 53 | + sum(n_insert_queries) AS n_insert_queries, sum(n_update_queries) AS n_update_queries, sum(n_delete_queries) AS n_delete_queries, sum(n_truncate_queries) AS n_truncate_queries |
| 54 | + FROM relaccess_stats_tmp GROUP BY relid |
| 55 | + ) |
| 56 | + INSERT INTO relaccess_stats_tmp_aggregated |
| 57 | + SELECT relid, |
| 58 | + (SELECT relname FROM relaccess_stats_tmp w WHERE w.relid = wo.relid AND greatest(wo.last_read, wo.last_write) IN (w.last_read, w.last_write) LIMIT 1) AS relname, |
| 59 | + (SELECT last_reader_id FROM relaccess_stats_tmp w WHERE w.relid = wo.relid AND wo.last_read = w.last_read LIMIT 1) AS last_reader_id, |
| 60 | + (SELECT last_writer_id FROM relaccess_stats_tmp w WHERE w.relid = wo.relid AND wo.last_write = w.last_write LIMIT 1) AS last_writer_id, |
| 61 | + last_read, |
| 62 | + last_write, |
| 63 | + n_select_queries, |
| 64 | + n_insert_queries, |
| 65 | + n_update_queries, |
| 66 | + n_delete_queries, |
| 67 | + n_truncate_queries FROM aggregated_wo_relname_and_user AS wo'; |
| 68 | + EXECUTE 'DROP TABLE IF EXISTS relaccess_stats_tmp'; |
| 69 | + EXECUTE 'INSERT INTO relaccess.relaccess_stats |
| 70 | + SELECT relid, relname, last_reader_id, last_writer_id, last_read, last_write, 0, 0, 0, 0, 0 |
| 71 | + FROM relaccess_stats_tmp_aggregated stage |
| 72 | + WHERE NOT EXISTS ( |
| 73 | + SELECT 1 FROM relaccess.relaccess_stats orig WHERE orig.relid = stage.relid)'; |
| 74 | + EXECUTE 'UPDATE relaccess.relaccess_stats orig SET |
| 75 | + relname = stage.relname, |
| 76 | + n_select_queries = orig.n_select_queries + stage.n_select_queries, |
| 77 | + n_insert_queries = orig.n_insert_queries + stage.n_insert_queries, |
| 78 | + n_update_queries = orig.n_update_queries + stage.n_update_queries, |
| 79 | + n_delete_queries = orig.n_delete_queries + stage.n_delete_queries, |
| 80 | + n_truncate_queries = orig.n_truncate_queries + stage.n_truncate_queries |
| 81 | + FROM relaccess_stats_tmp_aggregated stage |
| 82 | + WHERE orig.relid = stage.relid'; |
| 83 | + EXECUTE 'UPDATE relaccess.relaccess_stats orig SET |
| 84 | + last_reader_id = stage.last_reader_id, last_read = stage.last_read |
| 85 | + FROM relaccess_stats_tmp_aggregated stage |
| 86 | + WHERE orig.relid = stage.relid AND orig.last_read < stage.last_read'; |
| 87 | + EXECUTE 'UPDATE relaccess.relaccess_stats orig SET |
| 88 | + last_writer_id = stage.last_writer_id, last_write = stage.last_write |
| 89 | + FROM relaccess_stats_tmp_aggregated stage |
| 90 | + WHERE orig.relid = stage.relid AND orig.last_write < stage.last_write'; |
| 91 | + EXECUTE 'DROP TABLE IF EXISTS relaccess_stats_tmp_aggregated'; |
| 92 | +END |
| 93 | +$func$; |
| 94 | + |
| 95 | +CREATE FUNCTION relaccess.relaccess_stats_init() RETURNS VOID AS |
| 96 | +$$ |
| 97 | + WITH relations AS ( |
| 98 | + SELECT oid as relid, relname, relowner FROM pg_catalog.pg_class WHERE relkind in ('r', 'v', 'm', 'f', 'p') |
| 99 | + ) |
| 100 | + INSERT INTO relaccess.relaccess_stats |
| 101 | + SELECT relid, relname, relowner, relowner, '2000-01-01 03:00:00', '2000-01-01 03:00:00', 0, 0, 0, 0, 0 |
| 102 | + FROM relations AS all_rels WHERE NOT EXISTS(SELECT 1 FROM relaccess.relaccess_stats orig WHERE orig.relid = all_rels.relid); |
| 103 | +$$ LANGUAGE SQL VOLATILE; |
| 104 | + |
| 105 | +-- This utility view shows **ONLY** stats on **EXISTING** partitioned tables in aggregated form |
| 106 | +CREATE VIEW relaccess.relaccess_stats_root_tables_aggregated AS ( |
| 107 | + WITH RECURSIVE parents AS ( |
| 108 | + SELECT inhrelid AS child, inhparent AS parent FROM pg_inherits |
| 109 | + UNION ALL |
| 110 | + SELECT prev.child, next.inhparent AS parent FROM parents AS prev JOIN pg_inherits AS next ON prev.parent = next.inhrelid |
| 111 | + ), part_to_root_mapping AS ( |
| 112 | + SELECT DISTINCT child AS partid, min(parent) OVER (partition BY child) AS rootid FROM parents |
| 113 | + ), parts_including_roots AS ( |
| 114 | + SELECT rootid as partid, rootid FROM (SELECT DISTINCT rootid FROM part_to_root_mapping) AS p |
| 115 | + UNION |
| 116 | + SELECT * FROM part_to_root_mapping |
| 117 | + ), with_root_id AS ( |
| 118 | + SELECT part_tbl.rootid, stats.* FROM relaccess.relaccess_stats stats JOIN parts_including_roots part_tbl ON (stats.relid = part_tbl.partid) |
| 119 | + ), without_last_user AS ( |
| 120 | + SELECT rootid AS relid, |
| 121 | + rootid::regclass::text AS relname, |
| 122 | + max(last_read) AS last_read, |
| 123 | + max(last_write) AS last_write, |
| 124 | + sum(n_select_queries) AS n_select_queries, |
| 125 | + sum(n_insert_queries) AS n_insert_queries, |
| 126 | + sum(n_update_queries) AS n_update_queries, |
| 127 | + sum(n_delete_queries) AS n_delete_queries, |
| 128 | + sum(n_truncate_queries) AS n_truncate_queries |
| 129 | + FROM with_root_id outer_tbl GROUP BY rootid |
| 130 | + ) |
| 131 | + SELECT relid, |
| 132 | + relname, |
| 133 | + (SELECT last_reader_id FROM with_root_id w WHERE w.rootid = wo.relid AND wo.last_read = w.last_read LIMIT 1) AS last_reader_id, |
| 134 | + (SELECT last_writer_id FROM with_root_id w WHERE w.rootid = wo.relid AND wo.last_write = w.last_write LIMIT 1) AS last_writer_id, |
| 135 | + last_read, |
| 136 | + last_write, |
| 137 | + n_select_queries, |
| 138 | + n_insert_queries, |
| 139 | + n_update_queries, |
| 140 | + n_delete_queries, |
| 141 | + n_truncate_queries |
| 142 | + FROM without_last_user wo |
| 143 | +); |
0 commit comments