2011-11-10 88 views
4

我有一个600万行的SQLite表。从表格中删除所有数据的最佳方法是什么?

做DELETE FROM TABLE很慢;

删除表,然后重新创建它似乎更快。

我用它来进行数据库导入。

会丢掉表是一种更好的方法,或者有没有办法快速删除所有数据?

+0

你有没有尝试过'TRUNCATE TABLE'? –

+1

SQLite没有一个'TRUNCATE',但它应该做一个截断优化时,有没有'WHERE' – Lamak

+0

@Lamak我在MySQL知道DELETE没有WHERE相当于截断 –

回答

3

一个很大的区别是,DELETE FROM TABLE是DML和DROP TABLE是DDL。当涉及到数据库交易时,这是非常重要的。最后的结果可能是相同的,但这些操作是非常不同的。

如果它只是性能,你必须知道,那么可以放下并重新创建表。如果你需要在你的导入中使用事务,那么你必须知道DDL没有被覆盖,例如不能被回滚。

+0

目前,我所做的第一件事就是删除它,然后重新创建它,然后创建一个事务并导入数据。 – Jon

+0

..当你的交易必须回滚?桌子是空的吗?还是必须在导入失败之前包含数据? –

+0

没有它的空 – Jon

1

一般来说,DROP TABLE将是一个未记录的事务。 DELETE FROM将需要临时日志记录记录,直到DELETE语句完成。

0

我不认为SQLite的实现TRUNCATE但如果这样做,可能会比DELETE

1

TRUNCATE TABLE更好的性能是快了很多。

除了从甲骨文网站的以下解释了原因:

“删除”进行正常的DML。也就是说,它们对行进行锁定,产生重做(大量),并且它们需要UNDO表空间中的段。仔细删除块清除记录。如果发生错误,可以发出回滚以在提交之前恢复记录。删除不会放弃段空间,因此删除所有记录的表格将保留其所有原始块。

截断是DDL,从某种意义上说,作弊。截断将表格的高水位标记移回零。不采用行级锁,不生成重做或回滚。从表中取消初始化的所有扩展数据块(如果您将MINEXTENTS设置为1以外的任何值,那么将保留该数据块的范围而不仅仅是初始值)。通过重新定位高位标记,可以防止读取任何表格数据,因此它们与删除效果相同,但没有任何开销。只有一个小问题:截断是一个DDL命令,所以如果你决定犯了错误,你就不能回滚它。 (当然,你不能有选择地截断 - 不允许使用“WHERE”子句,这与删除不同)。

通过重置高水位标记,truncate防止读取任何表数据,因此它们与删除具有相同的效果,但没有开销。但是,必须牢记截断的一个方面。因为Truncate是DDL,所以它在它作用之前发出一个COMMIT,然后在另一个COMMIT之后发出,所以不可能回滚事务。

请注意,默认情况下,即使未指定DROP STORAGE,TRUNCATE也会丢弃存储。

+0

一些瓶颈对不起,没看到乌尔使用SQLite。我认为这个帖子回答你的问题。 http://stackoverflow.com/questions/4280041/sqlite-truncate-a-table-if-exists – DeanOC

+0

这是一个非常准确的回答一个问题,用户也没有问。用户正在与SQLite合作,这是Oracle的一个非常不同的动物。 –

+0

@Larry勒斯蒂格 - 是的,我不知道,TRUNCATE不可用。我的错。也就是说,为什么TRUNCATE速度更快的要点与Oracle以外的其他实施TRUNCATE的DB相关,例如, SQL Server。 – DeanOC

相关问题