数据仓库里一半的表没人用——数据资产盘点和治理怎么做?
先说结论
数据资产盘点的核心目标是回答两个问题:① 这张表有没有人在用?② 这张表的价值和成本是否匹配?
盘点的方法是:利用操作元数据(查询日志、血缘关系、任务调度)来判断每张表的使用情况,然后分类处理——活跃表优化、低频表降级、僵尸表下线。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
你有没有发现,数据仓库里的表越来越多,但真正在用的可能不到一半?很多表是几年前某个需求建的,需求做完了表还在,ETL还在跑,每天消耗着计算和存储资源。这种「僵尸表」是数据治理里最容易被忽视但ROI最高的治理方向。我在某知名出海硬件品牌做数据平台时,通过数据资产盘点,下线了30%的无用表,每月节省了数千美元的存储和计算成本。
僵尸表是怎么来的
我在出海硬件公司接手数据平台时,数仓里有400+张表。做完盘点后发现:
• 活跃表(每天有查询或依赖):约180张,占45%
• 低频表(每月查1-2次):约80张,占20%
• 僵尸表(90天以上无人查询):约140张,占35%
这些僵尸表的来源主要有四种:
① 需求下线后表没删。某个功能迭代或A/B测试结束后,对应的分析表不需要了,但没人清理。
② 重复建表。不同的分析师为了同一个需求各自建表,最后只用了一张,其他的就废弃了。
③ 中间表没清理。开发过程中的临时表、调试表,上线后忘了删。
④ 人员离职。表的创建者离职了,没人知道这张表是干嘛的,不敢删。
-- 第一步:找出僵尸表——90天以上无人查询的表
SELECT
t.table_name,
t.table_schema AS db_name,
t.create_time,
COALESCE(q.last_query_time, t.create_time) AS last_access_time,
DATEDIFF(CURRENT_DATE, COALESCE(q.last_query_time, t.create_time)) AS idle_days,
s.total_size_gb,
s.partition_count
FROM information_schema.tables t
LEFT JOIN (
SELECT table_name, MAX(query_time) AS last_query_time
FROM sys.query_log
WHERE query_time >= DATE_SUB(CURRENT_DATE, 180)
GROUP BY table_name
) q ON t.table_name = q.table_name
LEFT JOIN meta_table_stats s ON t.table_name = s.table_name
WHERE DATEDIFF(CURRENT_DATE, COALESCE(q.last_query_time, t.create_time)) > 90
ORDER BY s.total_size_gb DESC NULLS LAST;
数据资产分级管理
盘点完之后,不能一刀切处理。我的做法是把所有表分成四个等级:
| 资产等级 | 定义 | 管理策略 | 成本策略 |
|---|---|---|---|
| A级(核心资产) | 支撑P0/P1报表的表 | SLA监控+质量校验+字段注释100% | 不限制 |
| B级(重要资产) | 支撑日常分析的表 | 质量校验+字段注释>80% | 正常保留 |
| C级(低频资产) | 偶尔使用的分析表 | 降低存储等级(如S3低频存储) | 降级存储 |
| D级(待下线) | 90天+无人使用 | 通知owner→30天公示→下线 | 下线节省成本 |
下线流程:怎么安全地删表
删表是最怕出事故的操作。万一删了一张看起来没人用、但实际上有一个月度报表在用的表,就是生产事故。所以下线必须有严格的流程:
Step 1:数据扫描。通过查询日志确认90天内无人查询。同时检查血缘系统,确认没有下游任务依赖。
Step 2:通知owner。找到表的创建者(或所属团队),告知计划下线,给他们一周时间确认。
Step 3:标记公示。在表名前加_deprecated_前缀,或者在元数据中标记状态为deprecated。公示30天。
Step 4:停ETL。先停止表的ETL产出任务,但保留历史数据。观察一周看有没有人反馈。
Step 5:归档删除。如果公示期内无人反对,把数据归档到低成本存储(如S3 Glacier),然后删除线上表。
-- 安全下线流程的SQL实现
-- Step 3: 标记废弃(重命名加前缀)
ALTER TABLE dws_old_report RENAME TO _deprecated_dws_old_report;
-- Step 4: 停止ETL后检查是否有人报错
-- 在监控系统中观察是否有查询 _deprecated_ 开头的表
SELECT table_name, user_name, query_time
FROM sys.query_log
WHERE table_name LIKE '_deprecated_%'
AND query_time >= DATE_SUB(CURRENT_DATE, 7);
-- Step 5: 归档到低成本存储
-- AWS: ALTER TABLE ... SET LOCATION 's3://archive-bucket/...';
-- 或者直接导出为Parquet文件到归档路径
-- 确认无误后DROP TABLE
成本优化:治理的直接价值
数据资产治理最直观的价值就是成本节省。我在出海硬件公司做完一轮盘点后的效果:
| 优化项 | 措施 | 节省效果 |
|---|---|---|
| 下线僵尸表 | 删除140张无用表及其ETL任务 | 存储减少2TB,计算减少500+任务/天 |
| 降级低频表 | 80张表从热存储改为冷存储 | 存储成本降低40% |
| 合并重复表 | 35张重复表合并为12张 | ETL任务减少23个 |
| 清理临时表 | 清理dev_/tmp_/test_开头的表 | 存储减少500GB |
综合下来,每月节省了大约3000美元的云计算成本。这个数字可以直接汇报给领导,非常有说服力。
面试高频追问
追问一:怎么判断一张表是「没人用」还是「偶尔用」?
主要看查询日志。我的标准是:90天内没有任何查询记录的表算僵尸表。但要注意两个特殊情况:一是月度/季度报表可能30天才查一次,不能按日活判断,要看90天周期;二是有些表虽然没有被直接查询,但被其他ETL任务作为上游依赖在用,需要检查血缘。
追问二:下线了一张表结果有人要用怎么办?
这就是为什么要有归档步骤——数据不是真的删了,而是归档到低成本存储。如果有人在归档后需要这张表,可以从归档恢复。我们设了6个月的归档保留期,6个月后才真正删除。这给了足够的缓冲时间。
追问三:数据资产盘点多久做一次?
首次盘点做一次全量,之后每季度做一次增量。增量盘点主要看:新增了哪些表、有哪些表从活跃变成低频/僵尸。我建议把盘点脚本自动化——每月自动生成一份「数据资产健康报告」,包含僵尸表清单、成本分布、注释覆盖率等指标。
实战踩坑
我在做数据资产盘点时踩过一个坑。有一张表叫dws_user_cohort,查询日志显示90天没人查过,按规则应该下线。但在准备下线时,产品经理突然说:「这张表是给每季度的投资人汇报用的,上次用是3个月前,下次马上要用了。」
这个案例让我完善了下线流程——除了看查询日志,还要看表的业务标签。有些表虽然查询频率低,但业务价值很高(比如投资人报表、审计报表)。后来我在元数据里加了一个「业务重要性」标签,标了「高」的表即使90天没查也不会自动进入下线流程。
-- 改进的僵尸表判定逻辑:排除高重要性标签的表
SELECT
t.table_name,
t.idle_days,
t.total_size_gb,
m.business_importance,
CASE
WHEN m.business_importance = 'HIGH' THEN 'KEEP'
WHEN t.idle_days > 90 AND t.total_size_gb > 1 THEN 'ARCHIVE'
WHEN t.idle_days > 90 THEN 'DROP'
WHEN t.idle_days > 60 THEN 'WARNING'
ELSE 'ACTIVE'
END AS action
FROM zombie_table_candidates t
LEFT JOIN meta_table_catalog m ON t.table_name = m.table_name;
-- business_importance = HIGH 的表需要人工确认才能下线
解决方案:加了业务重要性标签后,下线流程的准确率从约90%提升到了99%以上。再也没出现过误下线核心表的情况。
总结
数据资产盘点的核心流程:扫描僵尸表→分级管理→安全下线→成本优化。面试时重点讲两个点:一是用查询日志+血缘来判断表的使用情况,二是有一个安全的下线流程(标记→公示→停ETL→归档→删除)。再加上成本节省的量化数据,就很有说服力。
下一篇聊一个数据清洗中最常遇到的问题:NULL值占了30%,到底该怎么处理?
你们数仓里有多少张表?僵尸表占比大概多少?评论区聊聊~
关注「Wood聊大数据」| 9年大数据老兵,聊技术、聊职场、聊成长