我必须做大约20,000次手术。我需要确保这个名字'我所拥有的是在数据库中。以下哪种模式会更有效?为什么?
(1)in 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)INSERT IGNORE
for item in items:
cursor.execute('INSERT IGNORE INTO names VALUES (%s,)', item.name)
答案 0 :(得分:1)
这里显而易见的答案是:测试,不要猜。
但我很确定我能猜到,因为你在这里遇到了算法复杂性问题。
针对in
检查list
需要扫描整个列表并比较每个条目。如果你对20000个项目而不是2000个列表条目这样做,那就是40000000比较。除非您通过这样做几乎完全跳过所有20000条SQL语句,否则它几乎肯定是一种悲观。
然而,稍微改变一下,它可能是一个有用的优化:
针对in
检查set
几乎是即时的。如果你为20000个项目而不是2000个设置条目执行此操作,那就是20000个哈希值和查找。即使只有几千个SQL查询,也很容易保存。如果您使用的是Python 2.7或更高版本,则只需existing_names = { … }
而不是[ … ]
。
如果您想知道,在数据库内部(假设您在列上有索引),它使用树结构,因此每次查找都需要对数时间。即使对于二叉树(过高估计实际成本),每次查找的比较都不足11,但不如1,但它比2000好很多(另外,当然,搜索将会被优化,因为它是数据库必须做得很好的核心内容之一。)
最后,至少对于一些数据库库,您可以通过批量插入来获得更大的加速 - 可能使用executemany
,或者可能准备和加载批量SQL,因此您可能正在优化错误的位置
答案 1 :(得分:0)
我会使用方法2.但是,如果你没有名字的唯一索引,你的第二种方法肯定不会确保你的名字是唯一的。
如果您需要有关创建唯一索引的更多信息,可以找到它Here。
您的第一种方法似乎效率低于第二种方法,因为您必须首先获取唯一名称列表,然后测试它是否与循环中的任何名称都不匹配。
而在第二种方法中,维护唯一索引可能比第一种方法占用更多的开销,但可能比在DB外部进行处理更有效。在第二种方法中,您只需要一次点击数据库。