如何根据到期时间查找 table 使行过期?

How do I expire rows based on a lookup table of expiry times?

如果我有两个 tables:

items
    Id VARCHAR(26)
    CreateAt bigint(20)
    Type VARCHAR(26)

expiry
    Id VARCHAR(26)
    Expiry bigint(20)

items table 包含项目的创建时间和类型。然后另一个 table、expiry 是一个查找 table 来说明某些类型应该持续多长时间。每天 运行 查询以确保删除已过期的项目。

目前这个查询是在我们的应用程序中编写的,作为编程代码:

for item in items {
    expiry = expiry.get(item.Type)
    if (currentDate() - expiry.Expiry > item.CreateAt) {
        item.delete()
    }
}

当我们只有几千个项目时这很好,但现在我们有数千万个项目需要大量时间 运行。有没有办法将其放入 SQL 语句中?

假设所有日期值实际上都是 UNIX 时间戳,您可以编写如下查询:

SELECT * -- DELETE
FROM items
WHERE EXISTS (
    SELECT 1
    FROM expiry
    WHERE expiry.id = items.type
    AND items.CreateAt + expiry.Expiry < UNIX_TIMESTAMP()
)

一旦确定查询选择了正确的行,请将 SELECT 替换为 DELETE。

如果存储的日期是自 UNIX 纪元以来的秒数,您可以使用此 PostgreSQL 查询:

DELETE FROM items
USING expiry
WHERE items.type = expiry.id
  AND items.createat < EXTRACT(epoch FROM current_timestamp) - expiry.expiry;

适用于任何地方的标准 SQL 解决方案是

DELETE FROM items
WHERE items.createat < EXTRACT(epoch FROM current_timestamp)
                       - (SELECT expiry.expiry FROM expiry
                          WHERE expiry.id = items.type);

在 Postgre 中效率可能较低SQL。

您的代码越来越慢,因为您在数据库外部的表之间进行了连接。

第二个减慢的方面是你一个一个地删除项目。 因此,使用提供的紧凑删除语句是正确的解决方案。

看来您正在使用类似 python-sqlalchemy 的东西。那里的代码是这样的:

items.delete().\
    where(items.c.type==\
        select([expiry.c.id]).\
             where(currentDate() - expiry.Expiry > item.c.CreateAt ))