首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >SQLITE删除需要很长时间

SQLITE删除需要很长时间
EN

Stack Overflow用户
提问于 2020-06-19 04:32:11
回答 1查看 92关注 0票数 0

我有一个表,看起来像这样:

代码语言:javascript
运行
复制
CREATE TABLE records (
    batchID TEXT,
    A       TEXT,
    A_id    REAL,
    B       TEXT,
    B_id    REAL,
    C       REAL,
    D       REAL,
    E       REAL,
    F       REAL,
    G       REAL,
    H       REAL,
    color   REAL,
    repair  REAL,
    data    BLOB,
    id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT
)

我对表中的一些列建立了索引。由于正直不是一个问题,我有:

代码语言:javascript
运行
复制
PRAGMA synchronous = "0"
PRAGMA journal_mode = "OFF"

db有频繁的插入,我的记录表中有大约200万行,db文件大小约为2 2GB。每隔几个小时,我就需要从记录表中删除200K行。我使用的是node js orm:

代码语言:javascript
运行
复制
db.driver.execQuery('DELETE FROM records WHERE A IN ? AND batchID = ?',
    [['a1', 'a2'], 'batch123'],
    function(err) {
    // do stuff here    
    });

在开始时,delete大约需要10秒,但是,在运行一个月后,delete语句可能需要一个多小时(!)(参见附加的日志中的性能图,其中我记录了删除时间-橙色圆圈,蓝色圆圈是节点的内存)。这是一个问题,因为在删除时,在节点中生成了新写请求。这些写请求在内存中排队,因为某个点节点使用了大量内存。(因为delete会锁定表并阻止写入)

我怀疑这是因为数据库正在变得碎片化。Vacuum对我来说不是一个选项,因为这是一个无法停止的产品,当我在sqlite db文件的副本上测试vacuum时间时,它花费了15 - 30分钟。从我的理解来看,自动真空不会有什么帮助,因为它不会压缩页面中的数据,而且会加剧碎片。我还尝试将页面大小设置为4096,但也没有帮助。performance graph

EN

回答 1

Stack Overflow用户

发布于 2020-06-19 15:19:06

默认情况下,SQLite insert或delete在隐式事务中执行,因此速度较慢。

来自https://www.sqlite.org/lang_transaction.html

读事务由SELECT语句启动,写事务由CREATE、DELETE、DROP、INSERT或UPDATE等语句(统称为“写语句”)启动。

来自常见问题19 https://www.sqlite.org/faq.html

插入非常慢-我每秒只能做几十次插入

缺省情况下,每个INSERT语句都是其自己的事务。但是,如果您使用BEGIN...COMMIT将多个INSERT语句括起来,那么所有的INSERT语句都会被分组到一个事务中。提交事务所需的时间在所有包含的insert语句中分摊,因此每个insert语句的时间大大减少。

编辑:在我写了这个答案之后,这个问题已经改变了,所以它可能看起来没有意义。

通常情况下,您不应在SQLite中使用自动增量,这是不必要的,并且会对性能产生不利影响,请参阅https://sqlite.org/autoinc.html

关键字AUTOINCREMENT会带来额外的CPU、内存、磁盘空间和磁盘I/O开销,如果不是严格需要,则应避免使用。它通常是不需要的。

在SQLite中,类型为integer PRIMARY KEY的列是ROWID的别名(没有ROWID表除外),ROWID始终是64位有符号整数。

在INSERT中,如果ROWID或integer主键列没有显式地指定一个值,那么它将自动填充一个未使用的整数,通常比当前使用的最大ROWID大1。无论是否使用AUTOINCREMENT关键字,都是如此。

如果AUTOINCREMENT关键字出现在INTEGER PRIMARY KEY之后,则会更改自动ROWID分配算法,以防止在数据库的生命周期中重用ROWID。换句话说,AUTOINCREMENT的目的是防止以前删除的行中的ROWID被重用。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62458903

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档