情况:需要在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()
问题:如果忽略速度,从编程的角度来看,哪种方法更好?并尽可能说明原因。
答案 0 :(得分:3)
从纯编程实践的角度来看,除了速度之外,没有区别。但是...
准备好的陈述是好的。但是,mass-insert产生了大量的变量绑定,SQLite可以处理的主机参数数量为upper limit,默认值为999。
因此,多插入很适合玩玩,但对于真实数据,您将使用循环。我可以提供的一个很好的建议是,您希望将循环包装在事务中,因为如果没有AFAIK,则每个插入都将是一个自动事务,这将极大地影响时间。 (另外,在循环的结尾而不是在循环内提交。)
编辑:根据Python文档,
默认情况下,sqlite3模块在数据修改语言(DML)语句(即
INSERT
/UPDATE
/DELETE
/REPLACE
之前隐式打开事务并提交在非DML,非查询语句(即SELECT
或上述以外的任何内容)之前隐式进行事务。
因此,您在#method1中的代码正在执行[{BEGIN
],INSERT
,COMMIT
,[BEGIN
],INSERT
,COMMIT
... BEGIN
由Python隐式发送以开始事务,而COMMIT
显式结束它。如果您按以下方式构建代码:
for item in data:
cursor.execute("INSERT INTO table(value1, value2, value3) VALUES (?,?,?)", item)
conn.commit()
然后,您在开头有一个隐式BEGIN
,在末尾有很多INSERTS
和一个显式COMMIT
。这样可以将您的代码速度提高10到20倍左右。