我有60亿行的Firebird表,我需要删除ca.表的一半。
表行包含汽车的gps位置,记录的时间戳和其他数据。表具有主键IdVehicle + TimeStamp和一个外键(进入Vehicle表)。没有其他键或索引或触发器。一辆车有10万至50万张记录。
我需要删除较旧的数据,例如。从所有车辆删除早于2015年3月1日的数据。我尝试了不同的方式,实际使用我最快的'execute block'
(使用主键)。首先,我阅读了一份早于1.3.2015的车辆记录。然后我将浏览各个记录并准备sql执行一个块,然后每50个条目执行一次firebird。
EXECUTE BLOCK AS BEGIN
DELETE FROM RIDE_POS WHERE IdVehicle = 1547 and date = '4.5.2015 8:56:47'
DELETE FROM RIDE_POS WHERE IdVehicle = 1547 and date = '4.5.2015 8:56:59'
DELETE FROM RIDE_POS WHERE IdVehicle = 1547 and date = '4.5.2015 8:57:17'
...... a total of 50 line
END
因此每800秒删除100万行(约1个记录,1毫秒)。
还有其他更快捷的删除记录的方法吗?
此外,这种方式我只能删除几百万行,然后我必须重新启动firebird,否则开始减速和阻塞(在测试服务器上没有其他数据库/应用程序)。从早期记录中快速清除并逐渐消耗更长时间。
对于方向,您在大表中常规擦除记录的速度有多快(不是完全擦除表格,而只是记录的一部分)。
答案 0 :(得分:2)
如果您要删除超过指定日期的所有记录,无论车辆是什么,那么查询中都没有包含execute block
的点,只是日期就足够了。即以下应该做,只是直接查询,不需要DELETE FROM RIDE_POS WHERE date < '2015-03-01'
:
foreach
答案 1 :(得分:1)
如果必须删除数千(或数百万)条记录,请不要在一次交易中执行此操作。你最好分几个步骤 - 删除例如1000条记录并提交,然后删除其他1000条和提交 - 它应该比在一次交易中删除一百万条记录更快。 1000不是一个规则,它取决于您的特定情况(您的记录有多大,他们通过外键使用&#34;删除级联&#34;有多少链接数据)。还要检查是否有&#34;删除&#34;触发器,也许可以暂时停用它们。
答案 2 :(得分:0)
也许合并的方法会有所帮助。
在日期添加(临时)索引:
CREATE INDEX IDX_RIDE_POS_date_ASC ON RIDE_POS (date)
写一个执行块:
EXECUTE BLOCK
AS
DECLARE VARIABLE V_ID_VEHICLE INTEGER;
BEGIN
FOR SELECT
DISTINCT ID_VEHICLE
FROM
RIDE_POS
INTO
:V_ID_VEHICLE
DO BEGIN
DELETE FROM RIDE_POS WHERE IdVehicle = :V_ID_VEHICLE AND date < '1.3.2015'
END
END
如果您不想再使用它,请删除索引。
DROP INDEX IDX_RIDE_POS_date_ASC'
我认为即使考虑到创建索引所需的时间,您仍然可以节省一些时间来删除记录。
答案 3 :(得分:0)
最后,我找到了问题所在。主要问题是我使用的是经典的Winforms应用程序(或IBExpert),这会导致阻塞并减慢查询速度。我曾经执行过块并删除数据部分,这解决了堵塞问题,但速度很慢。
解决方案是创建一个简单的控制台应用程序并从中运行查询。我离开主键并擦除它(没有添加或删除索引),删除记录的速度大约为65每毫秒(每16秒100万行)。
当我尝试删除主时间段并在datetime列上添加索引时,比擦除速度提高了约5-10%。