ほとんどのDBAPI実装は、フェッチされるときに行を完全にバッファリングします。したがって、通常、SQLAlchemy ORMが1つの結果を取得する前に、結果セット全体がメモリにあります。
しかし、その後、Query
動作は、オブジェクトに戻る前に、デフォルトで指定された結果セットを完全にロードすることです。ここでの理論的根拠は、単純なSELECTステートメント以上のクエリに関するものです。たとえば、1つの結果セットで同じオブジェクトIDを複数回返す可能性のある他のテーブルへの結合(積極的な読み込みで一般的)では、正しい結果を返すことができるように、行の完全なセットがメモリ内にある必要があります。部分的にしか入力されていない可能性があります。
つまり、Query
yield_per()
。この呼び出しにより、Query
が発生します バッチで行を生成し、バッチサイズを指定します。ドキュメントに記載されているように、これはコレクションの積極的な読み込みを行っていない場合にのみ適切であるため、基本的には、自分が何をしているのかを本当に理解している場合に適しています。また、基盤となるDBAPIが行をプリバッファリングする場合でも、そのメモリオーバーヘッドが存在するため、このアプローチは、使用しない場合よりもわずかに拡張性が高くなります。
私はほとんどyield_per()
を使用しません;代わりに、ウィンドウ関数を使用して上記で提案したLIMITアプローチのより良いバージョンを使用します。 LIMITとOFFSETには大きな問題があり、OFFSET値が非常に大きいと、クエリがどんどん遅くなります。これは、OFFSETがNの行をページングするためです。これは、同じクエリを1回ではなく50回実行するのと同じです。行数がどんどん増えています。ウィンドウ関数のアプローチでは、選択したいテーブルのチャンクを参照する一連の「ウィンドウ」値をプリフェッチします。次に、それらのウィンドウの1つから一度にプルする個別のSELECTステートメントを発行します。
ウィンドウ関数のアプローチは、ウィキのです そして私はそれを大成功で使用しています。
また、すべてのデータベースがウィンドウ関数をサポートしているわけではありません。 Postgresql、Oracle、またはSQLServerが必要です。少なくともPostgresqlを使用するIMHOは、間違いなく価値があります。リレーショナルデータベースを使用している場合は、最高のものを使用することをお勧めします。