2011-04-21 63 views
4

我试图从Facebook获取大量数据,并在处理它们时将对象添加到数据库中。例如,对于喜欢,我只是将他们作为发布类似人员的ID。但是,当我添加多个像我会遇到sqlalchemy完整性错误,因为主键不唯一。SqlAlchemy IntegrityError

处理这个问题的最佳方法是什么?每次我要添加一个新的类似于数据库的数据时,是否必须执行查询,查找它是否存在,如果存在则增加它的计数,如果不存在则创建一个新条目?

这看起来不是很多查询吗?你认为最好怎么做?

回答

6

你是否真的需要优化重载?可能不会,你正在使用SQLite。在这种情况下,简单的解决方案要好得多:

class Like(Base): 
    __tablename__ = 'Like' 
    id = Column(Integer, primary_key=True) 
    counter = Column(Integer, nullable=False, default=0) 


o = session.merge(Like(id=1)) 
session.flush() # Required when it's new record 
o.counter = Like.counter+1 
session.commit() 

有检查和插入之间的竞争条件,但我相信这不会在实践中击败你。

当你真的需要优化有点或解决这个竞争条件,有SQLite中,以避免检查一个INSERT OR IGNORE(有2个独立的语句尚未执行):

clause = Like.__table__.insert(prefixes=['OR IGNORE'], 
           values=dict(id=1, counter=0)) 
session.execute(clause) 
o = session.merge(Like(id=1, counter=Like.counter+1)) 
session.commit() 

终于有一个办法做到这一点在单个语句中使用INSERT OR REPLACE和子查询(也有其他方法可以做到这样的事情在大多数其他数据库,如ON DUPLICATE KEY在MySQL),但我怀疑它会给你明显的性能增益:

old = session.query(Like.counter).filter_by(id=1).statement.as_scalar() 
new = func.ifnull(old, 0) + 1 
clause = Like.__table__.insert(prefixes=['OR REPLACE'], 
           values=dict(id=1, counter=new)) 
session.execute(clause)