【问题标题】:Which is better - execute(INSERT) or executemany(INSERT)哪个更好 - execute(INSERT) 或 executemany(INSERT)
【发布时间】:2018-12-16 15:54:54
【问题描述】:

情况:需要在 SQLite 数据库中插入相当多的数据。

问题:我们可以使用两个语句来插入数据 -

data = [("111", "222", "333"), ("AAA", "BBB", "CCC"), ("XXX", "YYY", "ZZZ")]

#method1
for item in data:
    cursor.execute("INSERT INTO table(value1, value2, value3) VALUES (?,?,?)", item)
    conn.commit()

#method2
cursor.execute("INSERT INTO table(value1, value2, value3) VALUES(?,?,?)", data)
conn.commit()

问题:如果忽略速度,从编程的角度来看,哪个是更好的做法?如果可能,请解释原因。

【问题讨论】:

    标签: python python-3.x sqlite pysqlite


    【解决方案1】:

    从纯粹的编程实践来看,除了速度之外,并没有什么区别。不过……

    准备好的陈述是好的。但是,mass-insert 会进行大量的变量绑定,并且 SQLite 有一个upper limit 来表示它可以处理的主机参数数量,默认为 999。

    因此,多插入非常适合玩弄,但对于真实数据,您将使用循环。不过,我可以提供的一个好建议是,您需要将循环包装在事务中,因为没有它,AFAIK,每个插入都将是一个自动事务,这将极大地影响时间。 (另外,在循环结束时提交,而不是在循环内。)

    编辑:根据 Python 文档,

    默认情况下,sqlite3 模块在数据修改语言 (DML) 语句(即INSERT/UPDATE/DELETE/REPLACE)之前隐式打开事务,并在非 DML 之前隐式提交事务,非查询语句(即SELECT 或上述以外的任何内容)。

    所以您在#method1 中的代码正在执行 [BEGIN]、INSERTCOMMIT、[BEGIN]、INSERTCOMMIT... 且 BEGIN 隐式由 Python 发送开始一个事务,COMMIT 明确结束它。如果您像这样构建代码:

    for item in data:
        cursor.execute("INSERT INTO table(value1, value2, value3) VALUES (?,?,?)", item)
    conn.commit()
    

    然后你在开头有一个隐含的BEGIN,在结尾有很多INSERTS 和一个显式的COMMIT。这应该可以将您的代码加速 10-20 倍左右。

    【讨论】:

    • 您能否进一步详细说明“将循环包装在事务中”的含义?
    猜你喜欢
    • 2014-09-19
    • 1970-01-01
    • 2021-11-26
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 2011-11-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多