错误,是 Oracle 数据库在执行直接路径插入(Direct-Path INSERT) 操作(如 INSERT /*+ APPEND */ 或 SQL*Loader 直接路径加载)时,一个非常典型且常见的问题。
当使用 直接路径插入 (APPEND 提示) 批量插入数据时:
ORA-26028 错误。这是最直接的避免方法,但性能会下降。
-- 改用常规插入,不使用 APPEND 提示
INSERT INTO your_table (col1, col2, ...)
SELECT col1, col2, ...
FROM source_table;
如果确定要使用 APPEND,可以先禁用索引,插入完成后再重建。
-- 步骤1: 禁用索引
ALTER INDEX idx_name UNUSABLE;
-- 步骤2: 执行直接路径插入
INSERT /*+ APPEND */ INTO your_table (col1, col2, ...)
SELECT col1, col2, ...
FROM source_table;
COMMIT;
-- 步骤3: 重建索引 (自动处理无效状态)
ALTER INDEX idx_name REBUILD;
-- 或者批量重建所有无效索引
ALTER TABLE your_table ENABLE CONSTRAINT constraint_name; -- 如果是约束相关的索引
-- 或者
-- ALTER INDEX ALL ON your_table REBUILD; -- 需要指定具体索引或循环处理
这是最常见的生产实践。
-- 执行直接路径插入,允许索引失效
INSERT /*+ APPEND */ INTO your_table (col1, col2, ...)
SELECT col1, col2, ...
FROM source_table;
COMMIT;
-- 插入完成后,重建所有失效的索引
-- 方法一:逐个重建
ALTER INDEX idx_name_1 REBUILD;
ALTER INDEX idx_name_2 REBUILD;
...
-- 方法二:使用 PL/SQL 脚本批量重建
BEGIN
FOR rec IN (SELECT index_name FROM user_indexes
WHERE table_name = 'YOUR_TABLE' AND status = 'UNUSABLE') LOOP
EXECUTE IMMEDIATE 'ALTER INDEX ' || rec.index_name || ' REBUILD';
END LOOP;
END;
/
对于大型表,最佳方案是使用分区。
-- 假设主表是分区表,有一个空的临时分区 temp_part
-- 步骤1: 在临时分区上执行直接路径插入
INSERT /*+ APPEND */ INTO your_partitioned_table PARTITION (temp_part) ...
SELECT ...;
-- 步骤2: 交换分区 (此操作极快,且不影响主表索引)
ALTER TABLE your_partitioned_table
EXCHANGE PARTITION temp_part WITH TABLE staging_table
INCLUDING INDEXES WITHOUT VALIDATION;
-- 主表的全局索引保持有效!
一旦索引已经处于 UNUSABLE 状态,你需要重建它。
检查索引状态:
SELECT index_name, status FROM user_indexes WHERE table_name = 'YOUR_TABLE_NAME';
-- 或者查看更详细信息
SELECT index_name, status, partitioned FROM all_indexes WHERE table_name = 'YOUR_TABLE_NAME';
重建索引:
ALTER INDEX your_index_name REBUILD;
验证状态:
SELECT index_name, status FROM user_indexes WHERE index_name = 'YOUR_INDEX_NAME';
-- 确认 status 变为 'VALID'ALTER INDEX ... REBUILD PARTITION ...。VALID 状态。--方法/适用场景/优缺点
1,--避免使用 APPEND
数据量不大,对性能要求不高
✅ 简单安全❌ 速度慢
2,--先禁用再重建
知道哪些索引受影响,可接受停机
✅ 控制明确❌ 需要额外步骤
3,--插入后批量重建
大批量数据加载的标准做法
✅ 利用 APPEND 高性能✅ 流程清晰
4,--分区交换
大型分区表的最佳实践
✅ 极高性能,索引不受影响✅ 几乎无锁❌ 需要表结构支持
第2种方法的疑问,见下文:
但每次插入前禁用索引,插入后重建索引,这样频繁的重建索引,对数据库有什么影响吗?