首页 文章

如何在PostgreSQL中通过排序删除固定数量的行?

提问于
浏览
80

我正在尝试将一些旧的MySQL查询移植到PostgreSQL,但我遇到了这个问题:

DELETE FROM logtable ORDER BY timestamp LIMIT 10;

PostgreSQL没有主键,所以我不能使用子查询 . 另外,我想保留查询删除给定数字或记录的行为 - 例如,如果表包含30行但它们都具有相同的时间戳,我仍然想要删除10,尽管没关系哪10 .

所以;如何在PostgreSQL中通过排序删除固定数量的行?

编辑:没有主键意味着没有 log_id 列或类似 . 啊,遗留系统的乐趣!

6 回答

  • 0

    您可以尝试使用ctid

    DELETE FROM logtable
    WHERE ctid IN (
        SELECT ctid
        FROM logtable
        ORDER BY timestamp
        LIMIT 10
    )
    

    ctid 是:

    行版本在其表中的物理位置 . 请注意,尽管可以使用ctid非常快速地定位行版本,但如果行的ctid被VACUUM FULL更新或移动,则行的ctid将会改变 . 因此,ctid作为长期行标识符是无用的 .

    还有 oid 但只有在创建表时特别要求它才存在 .

  • 11

    Postgres文档建议使用数组而不是IN和子查询 . 这应该更快

    DELETE FROM logtable 
    WHERE id = any (array(SELECT id FROM logtable ORDER BY timestamp LIMIT 10));
    

    这个和其他一些技巧可以找到here

  • 117
    delete from logtable where log_id in (
        select log_id from logtable order by timestamp limit 10);
    
  • 1

    假设您要删除任何10条记录(没有订购),您可以这样做:

    DELETE FROM logtable as t1 WHERE t1.ctid < (select t2.ctid from logtable as t2  where (Select count(*) from logtable t3  where t3.ctid < t2.ctid ) = 10 LIMIT 1);
    

    对于我的用例,删除10M记录,结果更快 .

  • 2

    您可以编写一个循环删除单个行的过程,该过程可以使用参数来指定要删除的项目数 . 但与MySQL相比,这有点过分 .

  • 40

    如果您没有主键,则可以使用数组Where IN语法和复合键 .

    delete from table1 where (schema,id,lac,cid) in (select schema,id,lac,cid from table1 where lac = 0 limit 1000);
    

    这对我有用 .

相关问题