1

データベース(単一のテーブル)からの結果を照会する小さなプログラムを書いています。私はpython 3.3、sqlalchemy、およびpostgresデータベースを使用しています。

result = db_session.query(Data).all()
progress = 0
for row in result:
    update_progress_bar(progress, len(result))
    do_something_with_data(row)
    progress += 1

変数 'result' には数千行が含まれ、データの処理には時間がかかります。これが、単純なプログレスバーを導入して、どれくらいの時間がかかるかを示す理由です。問題は、合計時間の 30% がデータベース (最初の行) をクエリしていることです。そのため、プログラムを開始すると、進行状況バーが動き始める前に大きな遅延が発生します。さらに、すべての結果をメモリに保持する必要はありません。別々に処理できます。

上記のプログラムを変更して、すべての行をメモリにロードせずに、すべての行が受信されるまで行を 1 つずつ取得する方法はありますか? さらに、データのクエリと処理の進行状況を監視したいと考えています。

4

1 に答える 1

3

を呼び出さにクエリをループし、 を呼び出してバッチ サイズを設定する必要.all()あります.yield_per()

for row in db_session.query(Data).yield_per(10):
    do_something_with_data(row)

.all()実際、最初に結果セット全体をリストに変換するため、結果セットが大きい場合は遅延が発生します。代わりに、データベース API がサポートしている場合は、.yield_per()必要に応じて結果を取得する代わりに、設定の直後にクエリを反復処理します。

.count()返される行数を事前に知りたい場合は、最初に次のように呼び出します。

result = db_session.query(Data)
count = result.count()

for row in result.yield_per(10):
    update_progress_bar(progress, count)
    do_something_with_data(row)
    progress += 1

.count()最初に項目数を取得するようにデータベースに要求します。

を使用していても、データベースが結果行を事前キャッシュしている可能性があり、起動の遅延につながり.yield_per()ます。その場合、ウィンドウ化されたクエリを使用して、列の1 つの値の範囲に基づいてクエリをブロックに分割する必要があります。これが機能するかどうかは、正確なテーブル レイアウトによって異なります。

于 2013-04-11T12:08:41.643 に答える