17

我试图弄清楚如何使用 Python 3 中的 SQLAlchemy 将许多(大约 100k)记录插入到数据库中。一切都指向使用事务。但是,我对如何完成感到有些困惑。

有些页面声明您从 获得交易connection.begin(),其他地方说它是,这里session.begin()的这个页面说它是不存在的。session.create_transaction()

这是我正在尝试做的事情:

def addToTable(listOfRows):
    engine = create_engine('postgresql+pypostgresql:///%s' % db,echo = False)
    Session = sessionmaker(bind = engine)
    session = Session()
    table = myTable(engine,session)

    for row in listOfRows:
       table.add(row)
    table.flush() ### ideally there would be a counter and you flush after a couple of thousand records


class myTable:

    def __init__(self,engine,session):
       self.engine  = engine
       self.session = session
       self.transaction =createTransaction()# Create transaction code here

   def add(self,row):
       newRow = tableRow(row) ## This just creates a representation of a row in the DB
       self.transaction.add(newRow)
       self.transaction.flush()

   def flush(self):
       self.transaction.commit()
4

2 回答 2

33

我强烈建议您在继续使用 SQLAlchemy 之前完成这两个教程。他们真的很有帮助并解释了许多概念。之后,我建议您阅读Using the Session,因为这将继续解释 session 如何适应所有这些。

对于您的问题,有两种解决方案:一种使用 ORM,另一种使用 Core。前者更容易,后者更快。让我们先走容易的路。事务仅用于将所有语句包装到单个操作中。也就是说,如果某些事情失败了,您可以中止所有事情,并且不会在两者之间留下任何东西。所以你很可能想要一笔交易,但没有交易它也能工作。这是最快的方法:

with session.begin():
    session.add_all([tableRow(row) for row in listOfRows])

根据您的数据,SQLAlchemy 甚至可以优化您的INSERT语句,使其一次执行多个。这是发生了什么:

  • 事务开始使用session.begin
  • 添加数据(使用add_all,但多个循环add也可以)
  • 会话已提交。如果这里出现问题,事务将被中止,您可以修复错误。

所以这显然是一个好方法,但它不是最快的方法,因为 SQLAlchemy 必须遍历所有可能会产生一些开销的 ORM 算法。如果这是一次性数据库初始化,则可以避免使用 ORM。在这种情况下,不是创建 ORM 类 ( tableRow),而是创建一个包含所有键的字典(如何取决于数据)。您可以再次使用上下文管理器:

with engine.begin() as connection:
    connection.execute(tableRow.__table__.insert().
                       values([row_to_dict(row) for row in listOfRows]))

这很可能会稍微快一些,但也不太方便。它的工作方式与上面的会话相同,只是它从核心而不是 ORM 构造语句。

于 2013-11-11T22:35:34.590 回答
11

更新 2020-01-23

@javex 的答案已经过时了。

TLDR:您可以直接使用会话而无需调用begin. 只要确保autocommit设置为false

长答案:

请参阅会话文档 https://docs.sqlalchemy.org/en/13/orm/session_api.html

警告

Session.begin() 方法是与 Session 一起使用的更大模式的一部分,称为自动提交模式。这本质上是一种传统的使用模式,对于新应用程序来说不是必需的。Session 通常透明地处理“开始”的工作,而后者又依赖 Python DBAPI 透明地“开始”事务;使用现代会话编程模式时,无需显式开始事务。在 autocommit=False 的默认模式下,Session 会在事务的上下文中完成所有工作,因此只要您调用 Session.commit(),下一个事务就会在调用下一个数据库操作时隐式启动。有关更多背景信息,请参阅自动提交模式。

于 2020-01-23T11:34:06.227 回答