Castle.ActiveRecordの遅延読み取り
-
19-08-2019 - |
質問
データベース内の数百万件のレコードを定期的に(たとえば毎週)ループし、各行の結果に対してコードを実行する必要があるアプリケーションを作成しています。
テーブルが非常に大きいため、SomeObject.FindAll()を呼び出すと、140万行すべてを読み取り、SomeObject []のすべての行を返そうとしていると思われます。
SomeObject.FindAll()式を実行できる方法はありますが、よりDBMSに適した方法で値をロードしますか?
解決
FindAll()
なし-推測したように、指定したタイプのすべてのインスタンスを一度にロードしようとします(NHibernateのセットアップ方法によっては、膨大な数のそれを行うためのSQLクエリ)。
遅延読み込みはオブジェクトのプロパティでのみ機能します。たとえば、すべてのSomeObjectContainer
と一致するようにマップされたSomeObject
のリストをプロパティとして持つ永続型lazy="true"
がある場合、 foreach
を使用して、そのリストプロパティで<=>を実行すると、必要なものが得られます。デフォルトでは、NHibernateはリスト内の各要素に対してクエリを発行し、一度に1つだけをロードします。もちろん、読み取りキャッシュは非常に大きくなるので、おそらく大量にフラッシュする必要があります。
できることは、HQL(または埋め込みSQL)クエリを発行して、すべてのSomeObjectsのすべてのIDを取得し、FindByPrimaryKeyで関連するオブジェクトを1つずつフェッチすることです。繰り返しますが、特にエレガントではありません。
正直に言うと、そのような状況では、おそらくこれをストアドプロシージャのスケジュールされたメンテナンスジョブに変えます-データを操作するのではなく、オブジェクトで code を本当に実行する必要がない限りどういうわけか。オブジェクトの純粋主義者を困らせるかもしれませんが、特にこの種のバッチジョブのシナリオでは、ストアドプロシージャが正しい方法であることがあります。