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 の使用を続ける前に、両方のチュートリアルを実行することを強くお勧めします。それらは非常に役に立ち、多くの概念を説明しています。その後、 「セッションの使用」を読んで、セッションがこれらすべてにどのように適合するかを説明することをお勧めします。

あなたの問題には、2 つの解決策があります。1 つは ORM を使用し、もう 1 つは Core を使用します。前者はより簡単で、後者はより高速です。まずは楽な道を進みましょう。トランザクションは、すべてのステートメントを単一の操作にラップするためにのみ使用されます。つまり、何かが失敗した場合、そのすべてを中止することができ、その間に何かが残ることはありません。したがって、おそらくトランザクションが必要ですが、それがなくても機能します。これが最も速い方法です:

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

INSERTデータによっては、SQLAlchemy が一度に複数実行されるようにステートメントを最適化できる場合もあります。何が起こっているかは次のとおりです。

  • を使用してトランザクションが開始されますsession.begin
  • データが追加されます( を使用add_allしますが、複数のループでaddも問題ありません)
  • セッションがコミットされます。ここで何か問題が発生した場合、トランザクションは中止され、エラーを修正できます。

したがって、これは明らかに良い方法ですが、最速の方法ではありません。SQLAlchemy はすべての ORM アルゴリズムを実行する必要があり、多少のオーバーヘッドが発生する可能性があるためです。これが 1 回限りのデータベース初期化である場合は、ORM を回避できます。その場合、ORM クラス ( tableRow) を作成する代わりに、すべてのキーを持つ辞書を作成します (方法はデータに依存します)。ここでも、コンテキスト マネージャーを使用できます。

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

これはおそらくわずかに高速ですが、不便でもあります。上記のセッションと同じように機能するのは、ORM ではなく Core からステートメントを構築することだけです。

于 2013-11-11T22:35:34.590 に答える