truncate partition 是清空单个分区数据最快的方式,但仅适用于真正分区表且非间隔分区的最高区间;drop partition 更彻底但会令全局索引失效并破坏依赖结构;delete 性能最差。

TRUNCATE PARTITION 比 DELETE 快,但不是所有分区表都适用
直接 ALTER TABLE t TRUNCATE PARTITION p_name 是清空单个分区数据最快的方式——它跳过回滚段、不触发触发器、不写 undo 日志,毫秒级完成。但前提是:表必须是真正意义上的分区表(user_part_tables 有记录),且该分区不能是间隔(INTERVAL)分区的“最高区间”(否则报 ORA-14758)。常见误判是看到表名带“_2024”就以为是分区表,结果 SELECT partitioning_type FROM user_part_tables 返回空,强行执行会报 ORA-14048(alter operation not supported for this partition type)。
- 先确认是否分区:
SELECT partitioning_type FROM user_part_tables WHERE table_name = 'SALE_DATA' - 再查分区是否存在:
SELECT partition_name FROM user_tab_partitions WHERE table_name = 'SALE_DATA' AND partition_name = 'P_2024_Q1' - 间隔分区要额外检查:
SELECT interval FROM user_part_tables WHERE table_name = 'SALE_DATA',若非 NULL,禁止对最高分区用TRUNCATE PARTITION
DROP PARTITION 更彻底,但会破坏索引和依赖结构
ALTER TABLE t DROP PARTITION p_name 不仅清空数据,还删掉分区定义本身,释放的空间不可逆,且本地索引分区随之消失。但它比 TRUNCATE PARTITION 多一个关键副作用:全局索引(GLOBAL INDEX)立即变为 UNUSABLE,后续任何 DML 或查询都会失败,除非你加 UPDATE GLOBAL INDEXES 子句(Oracle 12c+ 支持,11g 不支持)。另外,如果该分区被物化视图日志或外键引用,命令会直接报错,比如 ORA-14080(partition cannot be dropped due to dependency)。
- 11g 环境下慎用
DROP PARTITION,除非你已接受重建全局索引的成本 - 执行前检查依赖:
SELECT owner, name, type FROM dba_dependencies WHERE referenced_owner = 'YOUR_SCHEMA' AND referenced_name = 'SALE_DATA' - 若需保留分区结构只清数据,别用
DROP,选TRUNCATE PARTITION
DELETE FROM ... PARTITION(...) 语义清晰,但性能最差
DELETE FROM sale_data PARTITION (p_2024_q1) WHERE create_time 这种写法合法,能精准删子集,也支持事务回滚和触发器。但它本质仍是逐行扫描 + 标记删除,undo 和 redo 日志量巨大,百万级数据可能跑十几分钟。更隐蔽的问题是:它不会降低高水位线(HWM),后续全表扫描仍扫旧块;也不释放空间,得额外 <code>ALTER TABLE ... SHRINK SPACE 才行。只有当你必须按条件删部分行(而非整分区)、且无法停业务时,才考虑它。
- 别指望它“快速”——它比
TRUNCATE PARTITION慢 10 倍以上 - WHERE 条件必须命中分区键,否则 Oracle 可能放弃分区裁剪,全表扫描
- 删完务必
COMMIT,否则锁住整个分区,阻塞其他会话
动态拼 SQL 清理多个分区时,HIGH_VALUE 解析不能偷懒
批量清理旧分区(如删掉 12 个月前的所有分区),不能靠 PARTITION_NAME 里截字符串判断时间,因为命名可能不规范(P_OLD_2023、Q1_2024、甚至中文)。正确做法是读 HIGH_VALUE 字段,用 EXECUTE IMMEDIATE 动态求值。例如 HIGH_VALUE 是 TO_DATE('2025-07-01','SYYYY-MM-DD'),必须构造 SELECT TO_DATE('2025-07-01','SYYYY-MM-DD') FROM DUAL 才能得到真实截止时间。硬编码解析逻辑(比如 SUBSTR(part_name, -6))在跨年或命名变更时必然出错。
- 别在存储过程中写死日期格式,
HIGH_VALUE的表达式类型由建表时指定,可能含NUMTOYMINTERVAL或MAXVALUE - 执行
TRUNCATE/DROP前,先加DBMS_LOCK.SLEEP(0.1)防并发冲突,避免两个 JOB 同时操作同一分区 - 异常捕获必须包含
ORA-14758和ORA-14404(分区不存在),否则脚本中断后状态不一致
真正快的前提是:你知道自己删的是什么分区、它属于哪种分区类型、有没有外部依赖。盲目套命令,三秒删完,三小时修索引。











