SQLAlchemy理想的承诺设计

时间:2011-04-20 14:52:30

标签: sqlalchemy commit

我在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)

1 个答案:

答案 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()