开发者

Does Ruby on Rails "has_many" array provide data on a "need to know" basis?

On Ruby on Rails, say, if the Actor model object is Tom Hanks, and the "has_many" fans is 20,000 Fan objects, then

actor.fans

gives an Array with 20,000 elements. Probably, the elements are not pre-populated with values? Otherwise, getting each Actor object from the DB can be extremely time consuming.

So it is on a "need to know" basis?

So does it pull data when I access actor.fans[500], and pull data when I access actor.fans[0]? If it jumps from each record to record, then it won't be able to optimize performance by doing sequential read, which can be faster on the hard disk because those records could be in the nearby sector / platter layer -- for example, if the program touches 2 random elements, then it will be faster just to read those 2 records, but what if it touches all elements in random order, then it may be faster just to read all records in a sequential way, and then process the random elements. But how will RoR know whether I am doing o开发者_JAVA百科nly a few random elements or all elements in random?


Why would you want to fetch 50000 records if you only use 2 of them? Then fetch only those two from DB. If you want to list the fans, then you will probably use pagination - i.e. use limit and offset in your query, or some pagination gem like will_paginate.

I see no logical explanation why should you go the way you try to. Explain a real situation so we could help you.

However there is one think you need to know wile loading many associated objects from DB - use :include like

Actor.all(:include => :fans)

this will eager-load all the fans so there will only be 2 queries instead of N+1, where N is a quantity of actors


Look at the SQL which is spewed out by the server in development mode, and that will tell you how many fan records are being loaded. In this case actor.fans will indeed cause them all to be loaded, which is probably not what you want.

You have several options:

  • Use a paginator as suggested by Tadas;
  • Set up another association with the fans table that pulls in just the ones you're interested in. This can be done either with a conditions on the has_many statement, e.g.
    has_many :fans, :conditions => "country of residence = 'UK'"
  • Specifying the full SQL to narrow down the rows returned with the :finder_sql option
  • Specifying the :limit option which will, well, limit, the number of rows returned.

All depends on what you want to do.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜