Firebird截断表/删除所有行

时间:2012-12-11 10:23:38

标签: sql firebird sql-delete truncate

我正在使用Firebird 2.5.1 Embedded。我已经做了通常用近20万行清空表格:

delete from SZAFKI

这是输出,看起来需要16秒,这是不可接受的。

Preparing query: delete from SZAFKI
Prepare time: 0.010s
PLAN (SZAFKI NATURAL)

Executing...
Done.
3973416 fetches, 1030917 marks, 116515 reads, 116434 writes.
0 inserts, 0 updates, 182658 deletes, 27 index, 182658 seq.
Delta memory: -19688 bytes.
SZAFKI: 182658 deletes. 
182658 rows affected directly.
Total execution time: 16.729s
Script execution finished.

Firebird没有TRUNCATE关键字。由于查询使用PLAN NATURAL,我尝试手动计划查询,如下所示:

delete from szafki PLAN (SZAFKI INDEX (SZAFKI_PK))

但是Firebird说“SZAFKI_PK不能在指定的计划中使用”(它是主键) 问题是我如何有效地清空表?丢弃和重新创建是不可能的。

3 个答案:

答案 0 :(得分:5)

根据我的评论回答

您可以尝试使用DELETE FROM SZAFKI WHERE ID > 0(假设ID为1或更高)。这将强制Firebird使用主键索引查找行。

我最初的假设是,这比没有索引的删除更糟糕。未编制索引的删除将对表的所有数据页进行顺序扫描并删除行(即:创建一个新的记录转换,即删除的存根记录)。当您使用索引时,它将按索引顺序查找行,这将导致随机遍历数据页(假设由于插入,删除和更新导致的大量记录版本,数据中存在高级别的碎片)。我原本预计这会变慢,但可能会导致Firebird只读取相关数据页(与事务相关的记录版本)而不是表的所有数据页。

答案 1 :(得分:2)

不幸的是,目前Firebird版本没有快速的方法可以对整个(大)表进行大量删除。当“已删除的内容”被垃圾收集时,您可以期待更高的延迟(在提交删除后在表中运行select *,您将看到)。您可以尝试在执行删除之前停用该表中的索引,并查看它是否有帮助。 如果您将该表用作某种临时存储,我建议您使用GTT功能。

答案 2 :(得分:0)

最快,只有这样才能摆脱FireBird表中的快速所有数据 - drop 创建再次表。至少目前正式版2.5.X。 FireBird 3.0的路线图中没有截断运算符,beta已经输出,所以很可能在3.0中也没有截断。

此外,您可以使用运算符 RECREATE - 与create相同的语法。如果表存在,则RECRATE删除它,然后创建新的。如果table不存在,则重新创建只是创建它。

 RECREATE TABLE Table1 (
   ID    INTEGER,
   NAME  VARCHAR(20),
   DATE  DATE,
   T     TIME
 );