4

有没有办法根据创建日期自动删除/删除所有表和与之关联的索引?

我在 Postgres 中找不到记录表/索引创建日期的内置/本机列。我正在运行 Postgres 8.4。我假设我可以做这样的事情(伪 SQL):

select all from pg_tables where creation_date is older than 90 days;

然后删除该选择的结果(对于 pg_indexes 相同)。但是,我找不到任何类型的表或索引创建日期。我可以自己安装某种创建日期跟踪器,但我认为 Postgres 中肯定会有一些本机的东西已经存储了这些信息……有吗?

谢谢

4

2 回答 2

7

旁注/免责声明:
这是一个坏主意,因为表创建时间不是 100% 可靠的,因为表可能由于表上的操作(例如 CLUSTER)而在内部被删除和重新创建。

除此之外,您可以像这样获得创建时间(假设 example-table-name of t_benutzer):

--select datname, datdba from pg_database;
--select relname, relfilenode from pg_class where relname ilike 't_benutzer';

    -- (select relfilenode::text from pg_class where relname ilike 't_benutzer')




SELECT 
    pg_ls_dir
    ,
    (
        SELECT creation
        FROM pg_stat_file('./base/'
            ||
            (
                    SELECT 
                        MAX(pg_ls_dir::bigint)::text 
                    FROM pg_ls_dir('./base') 
                    WHERE pg_ls_dir <> 'pgsql_tmp' 
                    AND  pg_ls_dir::bigint  <= (SELECT relfilenode FROM pg_class WHERE relname ILIKE 't_benutzer')
            )
            || '/' || pg_ls_dir
        )
    ) as createtime 
FROM pg_ls_dir(
    './base/' || 
    (
        SELECT 
            MAX(pg_ls_dir::bigint)::text 
        FROM pg_ls_dir('./base') 
        WHERE pg_ls_dir <> 'pgsql_tmp' 
        AND  pg_ls_dir::bigint  <= (SELECT relfilenode FROM pg_class WHERE relname ILIKE 't_benutzer') 
    ) 
) 

WHERE pg_ls_dir = (SELECT relfilenode::text FROM pg_class WHERE relname ILIKE 't_benutzer')

秘诀是在相应的表文件上使用 pg_stat_file。

-- http://www.greenplumdba.com/greenplum-dba-faq/howtofindtablecreationdateingreenplum


select 
    pg_ls_dir
    , 
    (
        select 
            --size 
            --access
            --modification 
            --change
            creation 
            --isdir
        from pg_stat_file(pg_ls_dir)
    ) as createtime 
from pg_ls_dir('.'); 

根据这篇文章PostgreSQL:表创建时间的评论,这 不是 100% 可靠的,因为表可能由于表上的操作(例如 CLUSTER)而在内部被删除并重新创建。

还有图案

/main/base/<database id>/<table filenode id> 

似乎是错误的,因为在我的机器上,来自不同数据库的所有表都具有相同的数据库 ID,并且似乎该文件夹已被替换为某个任意 inode 编号,因此您需要找到编号最接近您的表的文件夹inode id(最大文件夹名称,其中 folderid <= table_inode_id 和文件夹名称是数字)

简化版是这样的:

SELECT creation 
FROM pg_stat_file(
    './base/'
    ||
    (
        SELECT 
        MAX(pg_ls_dir::bigint)::text 
        FROM pg_ls_dir('./base') 
        WHERE pg_ls_dir <> 'pgsql_tmp' 
        AND  pg_ls_dir::bigint  <= (SELECT relfilenode FROM pg_class WHERE relname ILIKE 't_benutzer')
    )
    || '/' || (SELECT relfilenode::text FROM pg_class WHERE relname ILIKE 't_benutzer')
)

然后可以使用 information_schema 和 cte 使查询变得简单,或者创建自己的视图:

;WITH CTE AS
(
    SELECT 
        table_name 

        ,
        (
            SELECT 
                MAX(pg_ls_dir::bigint)::text 
            FROM pg_ls_dir('./base') 
            WHERE pg_ls_dir <> 'pgsql_tmp' 
            AND  pg_ls_dir::bigint  <= (SELECT relfilenode FROM pg_class WHERE relname ILIKE table_name)
        ) as folder 

        
        ,(SELECT relfilenode FROM pg_class WHERE relname ILIKE table_name) filenode
        
    FROM information_schema.tables
    WHERE table_type = 'BASE TABLE'
    AND table_schema = 'public'
)

SELECT 
    table_name 
    ,(
        SELECT creation 
        FROM pg_stat_file(
            './base/' || folder || '/' || filenode 
        )
    ) as creation_time
FROM CTE 

创建时间 PostGre

(使用 nhibernate 模式创建的所有表都创建,因此屏幕截图上所有表的时间大致相同是正确的)。

对于风险和副作用,请使用您的大脑和/或询问您的医生或药剂师;)

于 2013-09-17T14:34:07.557 回答
0

你确定你以正确的方式接近这个吗?您还没有解释您要做什么,但听起来也许通过使用日期列和分区方案会更好地解决。

于 2013-09-17T12:53:37.260 回答