truncate partition 比 delete 快,因其不扫描行、不写 undo 日志、不触发触发器,直接丢弃分区段;而 delete 逐行执行并校验约束。
truncate partition 为什么比 delete 快
因为 TRUNCATE PARTITION 不走行级扫描,不写 undo 日志,也不触发触发器,本质是直接丢弃整个分区的数据段(segment),只保留分区定义。而 DELETE 是逐行删除、生成回滚记录、还要校验外键和约束——哪怕加了 WHERE partition_col = 'xxx',优化器也未必能真正剪枝到分区粒度。
常见错误现象:DELETE FROM t WHERE dt = '2024-01-01' 看似只删一天数据,但若表没按 dt 正确分区,或查询未命中分区裁剪(partition pruning),实际可能扫全表。
- 必须确保表是已分区表(
PARTITION BY RANGE/LIST/HASH),且目标分区真实存在 -
TRUNCATE PARTITION不支持二级分区(subpartition)的单独截断,只能 truncate 到一级分区 - MySQL 8.0+ 和 Oracle 支持该语法;PostgreSQL 不支持,需用
TRUNCATE TABLE ... RESTART IDENTITY配合分区表继承或pg_truncate_partition扩展
MySQL 中执行 TRUNCATE PARTITION 的实操要点
语法是 ALTER TABLE tbl_name TRUNCATE PARTITION partition_name,不是 TRUNCATE TABLE ... PARTITION —— 写错会报 ERROR 1064。
使用场景:日志表按天分区,每天凌晨清空前天分区;或数仓中清理某业务线的旧分区。
- 分区名区分大小写(取决于
lower_case_table_names设置),建议用反引号包裹:ALTER TABLE log_events TRUNCATE PARTITION `p20240101` - 不能对包含唯一索引或主键的分区表执行该操作(MySQL 报
ERROR 1731),除非整个表的主键/唯一键都包含分区键 - 执行后
INFORMATION_SCHEMA.PARTITIONS中该分区的DATA_LENGTH和INDEX_LENGTH立即归零,但磁盘空间不一定立刻释放(InnoDB 可能延迟回收)
Oracle 下 TRUNCATE PARTITION 的权限与锁行为
Oracle 要求用户拥有 ALTER TABLE 权限,且分区必须处于 READ WRITE 状态。执行时仅对目标分区加 TX 锁,不影响其他分区的 DML,这点比全表 TRUNCATE 安全得多。
容易踩的坑:TRUNCATE PARTITION 在 Oracle 中不支持 REUSE STORAGE 子句(不像全表 truncate),所以每次都会重置高水位线(HWM),但不会释放到表空间,除非后续执行 ALTER TABLE ... SHRINK SPACE。
- 语法为:
ALTER TABLE sales TRUNCATE PARTITION p_jan2024;若分区名含特殊字符或小写,需双引号:ALTER TABLE sales TRUNCATE PARTITION "p_jan_2024" - 无法在有物化视图日志的表上直接 trunc 分区(报
ORA-12083),得先DROP MATERIALIZED VIEW LOG - 如果该分区上有本地索引(
LOCAL INDEX),索引会被自动维护;全局索引(GLOBAL INDEX)则默认失效,需加UPDATE GLOBAL INDEXES子句
误删分区后还能恢复吗
不能。TRUNCATE 是 DDL 操作,不进 undo,不记 binlog(MySQL 默认 row 格式下也不记录),Oracle 中也不进 flashback query 范围 —— 它就是把数据文件里那一块 segment 直接标记为可复用。
所以备份策略必须覆盖分区级元数据 + 物理备份(如 MySQL 的 xtrabackup 全量 + 增量,Oracle 的 RMAN 备份)。别指望从 slow log 或 general log 里捞出被删数据。
- MySQL 开启
binlog_format = STATEMENT时,TRUNCATE PARTITION会被记录为语句,但重放仍会丢失数据(因依赖分区存在性) - Oracle 启用
FLASHBACK ARCHIVE也无效,它只捕获 DML,不捕获 DDL - 最现实的补救:立刻停写,从最近一次物理备份中恢复整个表,再用逻辑导出工具(如
mysqldump --where或expdp)抽回其他分区数据
分区截断快是真的快,但快的前提是你已经确认过分区名、权限、依赖关系,并且备份就绪。少一个环节,秒级操作就变成小时级事故。










