如何使用执行块优化Firebird批量删除

时间:2016-03-12 19:18:18

标签: database query-optimization firebird delete-row

我有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,否则开始减速和阻塞(在测试服务器上没有其他数据库/应用程序)。从早期记录中快速清除并逐渐消耗更长时间。

对于方向,您在大表中常规擦除记录的速度有多快(不是完全擦除表格,而只是记录的一部分)。

4 个答案:

答案 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)

也许合并的方法会有所帮助。

  1. 在日期添加(临时)索引:

    CREATE INDEX IDX_RIDE_POS_date_ASC ON RIDE_POS (date)

  2. 写一个执行块:

    
    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
    

  3. 如果您不想再使用它,请删除索引。

    DROP INDEX IDX_RIDE_POS_date_ASC'

  4. 我认为即使考虑到创建索引所需的时间,您仍然可以节省一些时间来删除记录。

答案 3 :(得分:0)

最后,我找到了问题所在。主要问题是我使用的是经典的Winforms应用程序(或IBExpert),这会导致阻塞并减慢查询速度。我曾经执行过块并删除数据部分,这解决了堵塞问题,但速度很慢。

解决方案是创建一个简单的控制台应用程序并从中运行查询。我离开主键并擦除它(没有添加或删除索引),删除记录的速度大约为65每毫秒(每16秒100万行)。

当我尝试删除主时间段并在datetime列上添加索引时,比擦除速度提高了约5-10%。