質問

特定の期間中に更新されたテーブル、たとえば、テーブルごとのアクセス時間の下降順に確認したいと思います。

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作成スクリプトを使用してください。

ライセンス: CC-BY-SA帰属
所属していません dba.stackexchange
scroll top