前の期間にアクセスしたテーブル
-
16-10-2019 - |
質問
特定の期間中に更新されたテーブル、たとえば、テーブルごとのアクセス時間の下降順に確認したいと思います。
PostgreSQLのためにそれを取得するにはどうすればよいですか?
解決
テーブルの最後の変更に関する情報を取得できます xmin
, 、例:
select max(xmin::text::bigint) from t;
しかし、あなたは注意する必要があります 多くの警告の 含む モジュロとラップアラウンド と 冷凍XID.
テストベッド:
set role dba;
create role stack;
grant stack to dba;
create schema authorization stack;
set role stack;
--
create or replace function f(p_schema in text, p_table in text)
returns integer language plpgsql immutable as $$
declare
n integer;
begin
execute 'select max(xmin::text::bigint) from '||p_schema||'.'||p_table into n;
return n;
end;$$;
--
create table foo as select generate_series(1, 100) as id;
create table bar as select generate_series(1, 100) as id;
create table baz as select generate_series(1, 100) as id;
--
方法:
select table_name, f(table_schema, table_name)
from information_schema.tables
where table_schema='stack'
order by 2 desc;
/*
table_name | f
------------+--------
baz | 784657
bar | 784656
foo | 784655
*/
--
update foo set id=id+1 where id=100;
--
select table_name, f(table_schema, table_name)
from information_schema.tables
where table_schema='stack'
order by 2 desc;
/*
table_name | f
------------+--------
foo | 784658
baz | 784657
bar | 784656
*/
掃除:
drop schema stack cascade;
set role dba;
drop role stack;
他のヒント
Vanilla PostgreSQLのインストールでは、テーブルへのアクセスを記録しません。
必要な場合は、自分で実装する必要があります。そのためにトリガーを使用します。私は私のテーブルの多くにこのようなセットアップを使用しています。名前の列を追加します log_up
テーブルには、次のように更新を追跡します。
log_up timestamptz DEFAULT current_timestamp;
使用する timestamptz
(timestamp with time zone
)タイムゾーンで機能する:
トリガー関数:
CREATE OR REPLACE FUNCTION trg_log_up()
RETURNS trigger AS
$func$
BEGIN
NEW.log_up := current_timestamp;
RETURN NEW;
END;
$func$
LANGUAGE plpgsql VOLATILE;
引き金:
CREATE TRIGGER log_up
BEFORE UPDATE ON tbl
FOR EACH ROW EXECUTE PROCEDURE trg_log_up();
関連するいくつかの関連があります ロギングパラメーター さらに興味があるかもしれません。好き log_connections
また log_statement
.
アップデート:また、考慮してください 「タイムスタンプをコミット」 Postgresに追加されました 9.5:
すべてのテーブルにトリガーを追加します
データベースカタログをクエリすることにより、現在既存のすべてのテーブルのスクリプトを作成できます。たとえば、スキーマ内のすべてのテーブルのDDLステートメントを生成する public
:
SELECT string_agg(format('CREATE TRIGGER log_up BEFORE UPDATE ON %s '
'FOR EACH ROW EXECUTE PROCEDURE trg_log_up();'
, c.oid::regclass), E'\n')
FROM pg_namespace n
JOIN pg_class c ON c.relnamespace = n.oid
WHERE n.nspname = 'public';
-- AND c.relname ~~* '%tbl%' -- to filter tables by name
戻り値:
CREATE TRIGGER log_up BEFORE UPDATE ON tbl1 FOR EACH ROW EXECUTE PROCEDURE trg_log_up();
CREATE TRIGGER log_up BEFORE UPDATE ON tbl2 FOR EACH ROW EXECUTE PROCEDURE trg_log_up();
CREATE TRIGGER log_up BEFORE UPDATE ON tbl3 FOR EACH ROW EXECUTE PROCEDURE trg_log_up();
...
もちろん、彼らはすべて列を持っている必要があります log_up
タイプの timestamptz
最初。 DDLスクリプトを作成して、すべてのテーブルに列を同様の方法で追加できます。
最後にログのみ UPDATE
テーブルごと
あなたが最後に興味があるなら UPDATE
テーブルごとに、よりシンプルなソリューションが行われます。 1つの集中テーブルで追跡する方法は次のとおりです。
CREATE TABLE lastup (
schema_name text
, tbl_name text
, ts timestamptz
, PRIMARY KEY (schema_name, tbl_name)
);
引き金。に相談してください 特別な変数に関するマニュアル 私が使う:
CREATE OR REPLACE FUNCTION trg_lastup()
RETURNS trigger AS
$func$
BEGIN
UPDATE lastup
SET ts = current_timestamp
WHERE schema_name = TG_TABLE_SCHEMA
AND tbl_name = TG_TABLE_NAME;
RETURN NULL; -- For AFTER trigger irrelevant
END
$func$ LANGUAGE plpgsql;
テスト用のダミーテーブル:
CREATE TABLE dummy (id int);
INSERT INTO dummy VALUES (1), (2), (3);
ログテーブルにテーブルの行を入力します:
INSERT INTO lastup(schema_name, tbl_name) VALUES ('public', 'dummy');
引き金。私が使用することに注意してください AFTER
引き金 FOR EACH STATEMENT
(安い)。 ここのマニュアルの詳細。
CREATE TRIGGER log_up
AFTER UPDATE ON dummy
FOR EACH STATEMENT EXECUTE PROCEDURE trg_lastup();
テスト:
UPDATE dummy
SET id = id + 5
WHERE id < 3;
Voilá:
SELECT * FROM lastup;
または, 、 あなたがしたい場合は 空の更新を除外します (何も変更されていません)が、複数の更新された行が複数のログの更新をトリガーするため、より高いコストで:
CREATE OR REPLACE FUNCTION trg_lastup()
RETURNS trigger AS
$func$
BEGIN
IF OLD IS DISTINCT FROM NEW THEN -- check for changes
UPDATE lastup
SET ts = current_timestamp
WHERE schema_name = TG_TABLE_SCHEMA
AND tbl_name = TG_TABLE_NAME;
END IF;
RETURN NULL; -- For AFTER trigger!
END;
$func$ LANGUAGE plpgsql;
CREATE TRIGGER log_up
AFTER UPDATE ON dummy
FOR EACH ROW EXECUTE PROCEDURE trg_lastup(); -- per ROW instead of STATEMENT
に トリガーを作成します この体制に含めるすべてのテーブルについては、上記のような同様のDDL作成スクリプトを使用してください。