【问题标题】:Limiting the number of records in a Sqlite DB限制 Sqlite DB 中的记录数
【发布时间】:2013-09-07 20:30:58
【问题描述】:

我在这里尝试实现的是一个条件,其中一个 sqlite 数据库只保存最近的 1000 条记录。我有每条记录的时间戳。 立即发生的低效逻辑之一是检查记录总数。如果它们超过 1000,则只需删除掉出外围的那些。

但是,我必须对每个 INSERT 进行此检查,这会使事情变得非常低效。

还有什么更好的逻辑?我们可以用触发器做点什么吗?

SO:-

Delete oldest records from database

SQL Query to delete records older than two years

【问题讨论】:

  • 你有没有想过每次插入时表达到 1000 条记录的场景,你必须执行删除,最终 count(someId) 并不便宜。最好让记录保持增长并定期清理旧记录。
  • 按照同样的思路,维护小表大小的计划作业可能会满足您的要求。还可以考虑将记录移动到存档表而不是删除它们。你永远不知道什么时候你可能有理由去看它们。
  • @danisius - 你提出的方案在任何时候都是可能的,因为一旦记录数达到 1000,每次插入都会出现这种情况。
  • @DanBracuk 我绝对可以考虑存档,这也是一个好主意,但我正在努力寻找一种在数据库中而不是通过连接到数据库的应用程序来执行此操作的方法。我正在使用 Flex,所以如果我倾向于使用基于计时器的计划作业来尝试存档记录,那会让事情变得更糟。

标签: sql sqlite triggers


【解决方案1】:

您可以为此使用隐式 "rowid" 列。

假设您不以不同方式手动删除行:

DELETE FROM yourtable WHERE rowid < (last_row_id - 1000)

您可以使用API functionmax(rowid) 获取最后一个rowid

如果您不需要恰好 1000 条记录(例如,只想清理旧记录),则无需在每次插入时都这样做。在您的程序中添加一些计数器并执行 cleanup f.i.每 100 次插入一次。

更新:

无论如何,您要为每次插入或每次选择支付性能费用。所以选择取决于你有更多:INSERTs 或 SELECTs。

如果您没有那么多插入来关心性能,您可以使用以下触发器来保留不超过 1000 条记录:

CREATE TRIGGER triggername AFTER INSERT ON tablename BEGIN
     DELETE FROM tablename WHERE timestamp < (SELECT MIN(timestamp) FROM tablename ORDER BY timestamp DESC LIMIT 1000);
END

在时间戳列上创建唯一索引也应该是一个好主意(以防它已经不是 PK)。另请注意,SQLITE 仅支持 FOR EACH ROW 触发器,因此当您批量插入许多记录时,值得暂时禁用触发器。

如果 INSERT 太多,您在数据库方面无能为力。您可以通过添加像AFTER INSERT WHEN NEW.rowid % 100 = 0 这样的触发条件来减少触发频率。并且选择只需使用 LIMIT 1000(或创建适当的视图)。

我无法预测那会快多少。最好的方法是衡量您在特定情况下将获得多少性能。

【讨论】:

  • 感谢您的建议。现在的问题是记录最初没有按顺序插入,所以我不能将 rowid 作为参考 - 必须使用时间戳。对于超过一百万条记录的角色,我需要恰好有 1000 条记录。我只是在寻找避免每次进行搜索/查找操作时搜索和查找 1-5 百万条记录中的 1000 条的方法。
  • @Rohan 我已经用这个案例的可能解决方案更新了答案
  • @nevermind:不错的触发器,为什么不... id IN (SELECT id FROM ... WHERE clause)?我想说一下rowid:它的赋值行为会根据表是否有主[自动递增]键而改变,所以不要盲目相信它。来源:sqlite.org/autoinc.html.
  • @Alix Axel ... id IN (SELECT id FROM ... WHERE clause 也应该可以正常工作。唯一的区别可能在于性能,因为查询计划不同。我更愿意尽可能避免使用IN(...) 语句。
  • @Alix Axel 关于WHEN 声明:您的通知是正确的,这仅适用于AUTOINCREMENT PK。通常,想法是设置触发器的WHEN 条件以减少触发器调用的数量。这也可能是smth。喜欢... AFTER INSERT WHEN RANDOM() % 100 = 0 ON ...。但同样,这是优化步骤,只有在您确保“原始”触发器(没有 WHEN 语句)的性能不足以完成您的任务后才能完成。
猜你喜欢
  • 2021-04-19
  • 1970-01-01
  • 2011-02-11
  • 1970-01-01
  • 2015-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多