Pythonで処理した後、MySQLデータベースにXMLデータをインポートしようとしています。簡単にするために、SQLAlchemyを使用してデータベースにアクセスする1つのスクリプトからすべてを実行しています。
XMLファイルには約80,000のエントリがあり、xml.etree.cElementTree
のiterparse
メソッドを使用して処理し、ノードを使用した後にノードを削除して、メモリ使用量を約20MBに維持します。
SQLAlchemyを含めてデータベースに追加を開始すると、スクリプトがすべてのメモリを使い果たしてOSがメモリを強制終了するまで、メモリ使用量が1秒あたり約10MB増加します。
基本的に私のコードは次のようになります。
index = 0
for element in iterate_xml():
...
index += 1
session.add(Model(**data))
if index % 1000 == 0:
session.flush()
session.commit()
他に何を試すべきかわかりません。定期的.flush()
で.commit()
少しは役に立ちますが、問題は解決しません。
SQLAlchemyはこのタスクに適したツールではありませんか?
私はSQLAlchemyを次のように設定します:
Base = declarative_base()
engine = create_engine(config.SQLALCHEMY_DATABASE_URI, echo=False)
Session = sessionmaker(bind=engine, autoflush=False, expire_on_commit=False)
session = Session()
そして、私のテーブルは次のようになります。
columns = []
for name, datatype in structure.iteritems():
if isinstance(datatype, int):
datatype = String(datatype or 20)
column = Column(name, datatype)
columns.append(column)
metadata = MetaData(bind=engine)
table = Table('table_name', metadata,
Column('id', Integer, primary_key=True),
*columns
)
metadata.drop_all(engine)
metadata.create_all(engine)
class MyTable(Base):
__tablename__ = 'table_name'
__table_args__ = {
'autoload': True,
'autoload_with': engine
}
structure
列名をデータ型にマップする辞書です(XMLから生成されます)。
structure = {
'column_name': SQLAlchemyDataType,
...
}