我必须执行大约20,000次操作。我需要确保数据库中包含“名称”。以下哪种模式会更有效?为什么?

(1)在list()中

cursor.execute('select * from names')
existing_names = [item[0 for item in cursor.fetchall()] # len = 2,000
for item in items:
    if item.name not in existing_names:
        cursor.execute('INSERT INTO names VALUES (%s,)', item.name)


(2)插入忽略

for item in items:
    cursor.execute('INSERT IGNORE INTO names VALUES (%s,)', item.name)

最佳答案

显而易见的答案是:测试,不要猜测。

但我敢肯定,我可以猜到,因为您这里遇到了算法复杂性问题。

针对in检查list需要扫描整个列表并比较每个条目。如果您对20000个项目与2000个列表条目进行比较,那将是40000000个比较。除非您这样做几乎跳过了所有20000条SQL语句,否则几乎可以肯定是悲观的。

但是,稍作更改,可能是一个有用的优化:

针对in检查set几乎是即时的。如果对20000个项目与2000个set条目进行比较,则为20000个哈希和查找。即使仅数千个SQL查询,也很容易值得保存。如果您使用的是Python 2.7或更高版本,则只需existing_names = { … }而不是[ … ]即可。

如果您想知道,在数据库内部(假设您在该列上有一个索引),它使用的是树形结构,因此每次查找都需要对数时间。即使对于二叉树(它高估了实际成本),每次查找的比较结果也不足11次,虽然不及1次,但比2000年要好很多。(当然,该搜索将进行优化,因为这是数据库必须做好的核心工作之一。)

最后,至少对于某些数据库库,可以通过批量处理插入(例如使用executemany或准备并加载批量SQL)来获得更大的加速,因此无论如何您都在优化错误的位置。

关于python - INSERT IGNORE vs IN list(),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30471645/

10-10 12:55