【问题标题】:SqlAlchemy IntegrityErrorSqlAlchemy 完整性错误
【发布时间】:2011-08-10 16:14:21
【问题描述】:

我正在尝试从 facebook 获取一大堆数据,并在处理它们时将对象添加到数据库中。例如,对于点赞,我只是将它们设为发布点赞的人的 ID。但是,当我添加多个 like 时,我会在 sqlalchemy 中遇到完整性错误,因为主键不是唯一的。

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

这看起来不是很多查询吗?您认为最好的做法是什么?

【问题讨论】:

    标签: python database sqlite database-design sqlalchemy


    【解决方案1】:

    您真的需要针对重负载对其进行优化吗?可能不是,让您使用 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 和 subselect(在大多数其他数据库中还有其他方法可以做到这一点,例如 MySQL 中的ON DUPLICATE KEY),但我怀疑它会给你显着的性能提升:

    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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-05-16
      • 2013-07-12
      • 2015-06-09
      • 2012-07-04
      • 2018-06-08
      • 2016-09-26
      • 1970-01-01
      相关资源
      最近更新 更多