Castle.ActiveRecord 中的延迟读取
我正在编写一个应用程序,需要定期(例如每周)循环访问数据库中的数百万条记录,并对每行的结果执行代码。
由于表太大,我怀疑当我调用 SomeObject.FindAll() 时,它正在读取所有 140 万行并尝试返回 SomeObject[] 中的所有行。
有没有办法可以执行 SomeObject.FindAll() 表达式,但以更 DBMS 友好的方式加载值?
I am writting an application which needs to periodically (each week for example) loop through several million records ina database and execute code on the results of each row.
Since the table is so big, I suspect that when I call SomeObject.FindAll() it is reading all 1.4million rows and trying to return all the rows in a SomeObject[].
Is there a way I can execute a SomeObject.FindAll() expression, but load the values in a more DBMS friendly way?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
不适用于
FindAll()
- 正如您所猜测的,它将尝试一次加载指定类型的所有实例(并且,取决于您如何设置 NHibernate ,可能会出现以下问题)要执行此操作需要执行大量 SQL 查询)。延迟加载仅适用于对象的属性,因此,例如,如果您有一个持久类型
SomeObjectContainer
,它具有作为属性的SomeObject
列表,其映射方式应如此匹配所有SomeObject
并使用lazy="true"
,然后在该列表属性上执行foreach
,你会得到你想要的,有点; 默认情况下,NHibernate 会对列表中的每个元素发出查询,一次仅加载一个。 当然,读取缓存会变得巨大,因此您可能需要进行大量刷新。您可以做的是发出 HQL(甚至嵌入式 SQL)查询来检索所有 SomeObject 的所有 ID,然后一次循环一个 ID,使用 FindByPrimaryKey 获取相关对象。 同样,它也不是特别优雅。
老实说,在这种情况下,我可能会将其转变为存储过程中的计划维护作业 - 除非您确实必须在对象上运行代码而不是以某种方式操作数据。 它可能会惹恼对象纯粹主义者,但有时存储过程是正确的方法,特别是在这种批处理作业场景中。
Not with
FindAll()
- which, as you've surmised, will try to load all the instances of the specified type at one time (and, depending on how you've got NHibernate set up may issue a stupendous number of SQL queries to do it).Lazy loading works only on properties of objects, so for example if you had a persisted type
SomeObjectContainer
which had as a property a list ofSomeObject
mapped in such a way that it should match allSomeObject
s and withlazy="true"
, then did aforeach
on that list property, you'd get what you want, sort-of; by default, NHibernate would issue a query for each element in the list, loading only one at a time. Of course, the read cache would grow ginormous, so you'd probably need to flush a lot.What you can do is issue an HQL (or even embedded SQL) query to retrieve all the IDs for all SomeObjects and then loop through the IDs one at a time fetching the relevant object with FindByPrimaryKey. Again, it's not particularly elegant.
To be honest, in a situation like that I'd probably turn this into a scheduled maintenance job in a stored proc - unless you really have to run code on the object rather than manipulate the data somehow. It might annoy object purists, but sometimes a stored proc is the right way to go, especially in this kind of batch job scenario.