Sqlite executemany 和 DELETE
Posted
技术标签:
【中文标题】Sqlite executemany 和 DELETE【英文标题】:Sqlite executemany and DELETE 【发布时间】:2012-11-09 04:28:12 【问题描述】:删除执行很多似乎很慢(插入很好),我想知道是否有人知道为什么要花这么长时间
考虑下面的代码
import sqlite3
db = sqlite3.connect("mydb")
c = db.cursor()
c.execute("DROP TABLE IF EXISTS testing ")
c.execute("CREATE TABLE testing (val INTEGER);")
my_vals2 = [[x] for x in range(1,10000)]
def insertmany(vals):
c.executemany("INSERT INTO testing (val) VALUES (?)",vals)
db.commit()
def deletemany1(vals):
c.executemany("DELETE FROM testing WHERE val=?",vals)
db.commit()
def deletemany2(vals): #this is fastest even though im looping over to convert to strings and again to join ...
vals = ["'%s'"%v[0] for v in vals]
c.execute("DELETE FROM testing WHERE val IN (%s)"%",".join(vals))
#DELETE FROM TABLE WHERE x in (1,2,3...)
以下时间结果(timeit 给出了有趣的数据,所以:/)来自 ipython
%time insertmany(my_vals2)
#CPU times: user 0.60 s, sys: 0.00 s, total: 0.60 s Wall time: 0.60 s
%time deletemany1(my_vals2)
#CPU times: user 3.58 s, sys: 0.00 s, total: 3.58 s Wall time: 3.58 s
%time deletemany2(my_vals2)
#CPU times: user 0.02 s, sys: 0.00 s, total: 0.02 s Wall time: 0.02 s
为了完整起见,这里是 timeit 结果(但我认为 timeit 在第二次测试中被破坏(或者 ms 与第一次测试是不同的单位))
%timeit insertmany(my_vals2)
#1 loops, best of 3: 358 ms per loop
%timeit deletemany1(my_vals2)
#1 loops, best of 3: 8.34 ms per loop <- this is not faster than the above!!!! (timeit lies?)
%timeit deletemany2(my_vals2)
#100 loops, best of 3: 2.3 ms per loop
那么,为什么executemany 的删除速度如此之慢?
【问题讨论】:
比较有意思的是deletemany1
中代码生成的单个delete语句比deletemany2
快,deletemany2
使用的是python自己提供的executemany()
。
【参考方案1】:
SQLites 将表记录存储在 B+ 树中,按rowid
排序。
当您使用自动生成的rowid
插入时,所有记录都只是附加在表的末尾。
但是,删除时,SQLite 必须先搜索记录。如果id
列没有被索引,这会很慢;要么创建一个显式索引(由 John 提议),要么将该列声明为 INTEGER PRIMARY KEY
以使其成为 rowid。
如果不使用索引,即仅在批量插入后创建索引,则使用索引插入会变得更快。
您的最后一个删除命令一次删除所有记录。如果您知道要删除表中的所有记录,则可以通过使用 DELETE FROM testing
来进一步加快速度,它根本不需要查看任何记录。
【讨论】:
在这种情况下,它正在删除所有内容......但在现实世界中,它是用户选择的......无论如何,在你们两个之间,我想我对这种行为有一个更好的想法...... 【参考方案2】:我只是赌一把:因为它必须彻底搜索要删除的那些。 尝试使用索引并返回报告。
CREATE INDEX foo ON testing (val)
http://sqlite.org/lang_createindex.html
【讨论】:
嗯,删除时快得多,但现在插入时要慢得多......(+1反正我不知道sqlite支持索引)以上是关于Sqlite executemany 和 DELETE的主要内容,如果未能解决你的问题,请参考以下文章
Python3 | sqlite3:executemany() 不插入任何内容
Python Sqlite3 executemany 中的绑定数量不正确
使用 `executemany` 更新现有 SQLite3 数据库中的条目(使用 Python sqlite3)