You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PostgreSQL中识别未被应用使用与更新的表和列?

识别未被应用使用的数据库表与列(用于迁移)

一、用数据库内置监控功能直接查(最靠谱)

不同数据库的统计视图逻辑不同,直接用官方提供的工具比自定义查询精准得多:

MySQL/MariaDB

先开启性能监控(生产环境注意控制日志存储量),再筛选未被访问的表:

-- 启用表访问监控
UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME LIKE 'wait/lock/table/sql/handler';
UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME LIKE 'events_statements_%';

-- 筛选非系统库中未被访问的表
SELECT TABLE_SCHEMA, TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys')
AND TABLE_NAME NOT IN (
    SELECT DISTINCT OBJECT_NAME
    FROM performance_schema.events_statements_history_long
    WHERE OBJECT_TYPE = 'TABLE'
);

也可开启userstat参数后,通过INFORMATION_SCHEMA.TABLE_STATISTICS查看表的读写次数。

PostgreSQL

利用pg_stat_user_tables和pg_stat_user_columns视图,直接筛选长期无访问的对象:

-- 查90天内无任何读写扫描的表
SELECT schemaname, relname
FROM pg_stat_user_tables
WHERE (last_scan IS NULL OR last_scan < NOW() - INTERVAL '90 days')
  AND (last_idx_scan IS NULL OR last_idx_scan < NOW() - INTERVAL '90 days')
  AND (last_insert IS NULL OR last_insert < NOW() - INTERVAL '90 days')
  AND (last_update IS NULL OR last_update < NOW() - INTERVAL '90 days')
  AND (last_delete IS NULL OR last_delete < NOW() - INTERVAL '90 days');

-- 查长期未被读取且全为NULL的列(大概率未被使用)
SELECT schemaname, relname, attname
FROM pg_stat_user_columns
WHERE null_frac = 1
  AND (last_read IS NULL OR last_read < NOW() - INTERVAL '90 days');

SQL Server

注意:sys.dm_db_index_usage_stats在服务重启后会清空统计数据,建议结合长期监控结果:

-- 查未被任何索引访问的用户表
SELECT t.name AS TableName
FROM sys.tables t
LEFT JOIN sys.dm_db_index_usage_stats s ON t.object_id = s.object_id
WHERE s.object_id IS NULL
  AND t.type_desc = 'USER_TABLE';

-- 查未被读写的列
SELECT c.name AS ColumnName, t.name AS TableName
FROM sys.columns c
JOIN sys.tables t ON c.object_id = t.object_id
LEFT JOIN sys.dm_db_column_store_row_groups rg ON c.object_id = rg.object_id
WHERE rg.object_id IS NULL
  AND NOT EXISTS (
      SELECT 1 FROM sys.dm_db_index_usage_stats s
      WHERE s.object_id = t.object_id
      AND s.index_id IN (0,1)
  );

二、从应用层入手排查

数据库统计可能漏过间接访问(比如视图、存储过程),结合应用代码和日志能减少误判:

  • 代码扫描:用IDE全局搜索、grep或代码分析工具,提取所有SQL语句中的表和列,对比数据库结构找出未被引用的对象。
  • 日志分析:收集1-3个月的应用SQL日志,用Python/Shell脚本提取所有访问过的表和列,反向筛选未出现的对象。

三、临时标记验证(避免误操作)

如果拿不准对象是否被使用,给疑似未使用的表加触发器记录访问,观察一段时间:

-- MySQL示例:创建访问日志表和触发器
CREATE TABLE table_access_log (
    table_name VARCHAR(100),
    access_type VARCHAR(20),
    access_time DATETIME DEFAULT NOW(),
    accessed_by VARCHAR(100)
);

DELIMITER //
CREATE TRIGGER trg_suspect_table_read BEFORE SELECT ON your_suspect_table
FOR EACH ROW
BEGIN
    INSERT INTO table_access_log (table_name, access_type, accessed_by)
    VALUES ('your_suspect_table', 'READ', CURRENT_USER());
END //
DELIMITER ;

观察1-2个月,若日志无记录基本可确定该表未被使用。

四、之前查询没结果的常见原因

  • 统计数据被重置:比如SQL Server的监控视图在服务重启后清空,MySQL的Performance Schema默认未开启。
  • 忽略间接访问:通过视图、存储过程、触发器访问的表,直接查表统计会漏掉,需要关联这些对象的定义。
  • 时间范围太短:只查几天数据可能错过低频访问的表,建议至少覆盖1-3个月的统计周期。

内容的提问来源于stack exchange,提问作者Jayant Gupta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 16:52:00