我在SQLAlchemy上运行了一个Pylons后端。我有一个脚本从HTTP服务器读取XML文件树(它下载一个xml X,然后下载该X的子项,然后迭代子项,依此类推递归)。每个xml文件代表一个SQLAlchemy模型。
问题是我有成千上万的这些xml(有时是5000,有时是26000)。我能够使用HTTP池优化下载过程,但我似乎无法想到将模型提交到数据库的最佳方法。每次下载xml文件时,我都会为它创建一个orm对象并将其添加到我的会话中。
问题1:某些xml将在树中多次存在,因此我检查没有重复插入。检查我的代码是否最佳,或者我应该保留一个索引集合并使用它来检查重复项?
问题2:我的自动提交设置为False,因为我不想在每次添加时提交(不是因为它的设计不好,而是因为性能)。但我也不想在没有提交的情况下迭代数千个类别的整个树。因此,我创建了一个常数,我的代码在其上提交数据。这是一个好方法吗?什么是好的数字?值得一提的是,我事先并不知道我正在看多少xml。
以下是我的伪代码现在的样子(忽略语法错误):
count = 0
COMMIT_EVERY = 50
def recursion(parent):
global count, COMMIT_EVERY
pool = get_http_connection_pool(...)
sub_xmls = get_sub_xmls(pool, parent)
if sub_xmls == None:
return
for sub_xml in sub_xmls:
orm_obj = MyObj(sub_xml)
duplicate = Session.query(MyObj).filter(MyObj.id == orm_obj.id).first()
if not duplicate:
Session.add(orm_obj)
count = count + 1
if count % COMMIT_EVERY == 0:
Session.commit()
recursion(orm_obj.id)
recursion(0)
答案 0 :(得分:0)
我认为您应该在模型表中添加UniqueConstraint
并忘记查询重复项,然后只需:
try:
Session.add(orm_obj)
except IntegrityError:
log.warn("A duplicate found") #or just pass
良好的COMMIT_EVERY
值取决于您,测试不同的值,配置文件的性能,价值风险,我认为没有人可以用一些信息告诉您一个数字。
P.S:
if sub_xmls is None:
return
修改强>
可以将Sqlalchemy配置为在提交时插入 ,这就是为什么只在提交时获得IntegrityError
,或者只是每次进行添加,阅读文档或询问{{3我帮不了你。
或直接使用sql并获得性能:例如,这将引发每个重复(MySQL
语法的异常,检查您自己的DBRMS):
conn = Session.connection()
try:
curs = conn.execute("INSERT INTO table (id, value) VALUES (%s, %s)", (id, value))
except IntegrityError:
log.warn("A duplicate found: id=%s" % id)
finally:
#remember to close cursor
curs.close()