Dr. Dobb's Journal - December 2008 - (Page 27) d12weis_p4db 10/10/08 9:31 AM Page 27 Note that I’m calling #detect, not #find. This is because I want to invoke the method provided by the Enumerable module, and ActiveRecord::Base#find overrides Enumerable#find. This strategy works pretty well for a small number of commenters; however, #detect performs a sequential search, an O(n) operation. This method won’t perform well for a large value of n, when there are a lot of commenters. You might want to build a lookup hash for constant-time lookup, or O(1): # controller @commenter_lookup = post.commenters.inject(Hash.new) do |hash, user| hash[user.id] = user; hash end The view looks up the record for the comment’s user_id in the hash, and needs to call #first to pull the one and only record out of the array before getting the count. Code like this should be well commented, particularly the fact that it addresses a performance issue. There is another option for this kind of problem: denormalization. Solution 5: Denormalize “Normalize until it hurts. Denormalize until it works.” In a perfectly normalized database, there is only one representation of any particular fact. Taken to the extreme, this results in a space-efficient database with no chance of duplication or inconsistency. This is a wonderful ideal, but it comes at a cost: time-efficiency. We software developers walk a fine line between idealism and pragmatism. Active Record makes it very easy to denormalize the number of comments that Most unexpected performance challenges are related to querying the database Now the view can fetch the user for a given comment from the hash: # view @commenter_lookup[comment.user_id] Solution 4: Aggregate Another example of when the :include option isn’t enough is when you are fetching aggregated data. Let’s say you’d like to fetch the number of comments each user has created to display that next to the user’s name. If you calculate it user by user (via comment.user.comments.count), you’ll have another n+1 problem. One approach is to calculate the data for all relevant users in a single SQL query and build a lookup hash. # controller @comment_count_lookup = @post.comments.all( :select => 'user_id, COUNT(*) as num_comments', :group => 'user_id').group_by(&:user_id) This code, which could be in a controller or model, gets the number of comments for each user by grouping by user_id and counting the rows in each group with the SQL COUNT function. The #group_by method creates a hash where the key is the user_id (because it’s returned by the block), and the value is an array containing all items with that key. The view can use this hash to look up the count for a given user: # view December 2008 l www.ddj.com l Dr. Dobb’s Journal 27 http://www.accusoft.com/ddj http://www.accusoft.com/ddj http://www.ddj.com
Table of Contents Feed for the Digital Edition of Dr. Dobb's Journal - December 2008 Dr. Dobb's Journal - December 2008 Contents Friday Night Fish Fry Alia Vox Developer Diaries Conversations The Man Who Sold the Sky Performance on Rails LINQ-to-SQL and T-SQL A Remote Java RMI Registry Beyond B-Trees File Descriptors and Multithreaded Programs Effective Concurrency The Agile Edge Swaine's Flames Dr. Dobb's Journal - December 2008 Dr. Dobb's Journal - December 2008 - Dr. Dobb's Journal - December 2008 (Page Cover1) Dr. Dobb's Journal - December 2008 - Dr. Dobb's Journal - December 2008 (Page Cover2) Dr. Dobb's Journal - December 2008 - Dr. Dobb's Journal - December 2008 (Page 1) Dr. Dobb's Journal - December 2008 - Dr. Dobb's Journal - December 2008 (Page 2) Dr. Dobb's Journal - December 2008 - Dr. Dobb's Journal - December 2008 (Page 3) Dr. Dobb's Journal - December 2008 - Contents (Page 4) Dr. Dobb's Journal - December 2008 - Contents (Page 5) Dr. Dobb's Journal - December 2008 - Friday Night Fish Fry (Page 6) Dr. Dobb's Journal - December 2008 - Friday Night Fish Fry (Page 7) Dr. Dobb's Journal - December 2008 - Friday Night Fish Fry (Page 8) Dr. Dobb's Journal - December 2008 - Friday Night Fish Fry (Page 9) Dr. Dobb's Journal - December 2008 - Alia Vox (Page 10) Dr. Dobb's Journal - December 2008 - Alia Vox (Page 11) Dr. Dobb's Journal - December 2008 - Developer Diaries (Page 12) Dr. Dobb's Journal - December 2008 - Developer Diaries (Page 13) Dr. Dobb's Journal - December 2008 - Conversations (Page 14) Dr. Dobb's Journal - December 2008 - Conversations (Page 15) Dr. Dobb's Journal - December 2008 - The Man Who Sold the Sky (Page 16) Dr. Dobb's Journal - December 2008 - The Man Who Sold the Sky (Page 17) Dr. Dobb's Journal - December 2008 - The Man Who Sold the Sky (Page 18) Dr. Dobb's Journal - December 2008 - The Man Who Sold the Sky (Page 19) Dr. Dobb's Journal - December 2008 - Performance on Rails (Page 20) Dr. Dobb's Journal - December 2008 - Performance on Rails (Page 21) Dr. Dobb's Journal - December 2008 - Performance on Rails (Page 22) Dr. Dobb's Journal - December 2008 - Performance on Rails (Page 23) Dr. Dobb's Journal - December 2008 - Performance on Rails (Page 24) Dr. Dobb's Journal - December 2008 - Performance on Rails (Page 25) Dr. Dobb's Journal - December 2008 - Performance on Rails (Page 26) Dr. Dobb's Journal - December 2008 - Performance on Rails (Page 27) Dr. Dobb's Journal - December 2008 - Performance on Rails (Page 28) Dr. Dobb's Journal - December 2008 - LINQ-to-SQL and T-SQL (Page 29) Dr. Dobb's Journal - December 2008 - LINQ-to-SQL and T-SQL (Page 30) Dr. Dobb's Journal - December 2008 - LINQ-to-SQL and T-SQL (Page 31) Dr. Dobb's Journal - December 2008 - LINQ-to-SQL and T-SQL (Page 32) Dr. Dobb's Journal - December 2008 - LINQ-to-SQL and T-SQL (Page 33) Dr. Dobb's Journal - December 2008 - LINQ-to-SQL and T-SQL (Page 34) Dr. Dobb's Journal - December 2008 - A Remote Java RMI Registry (Page 35) Dr. Dobb's Journal - December 2008 - A Remote Java RMI Registry (Page 36) Dr. Dobb's Journal - December 2008 - A Remote Java RMI Registry (Page 37) Dr. Dobb's Journal - December 2008 - A Remote Java RMI Registry (Page 38) Dr. Dobb's Journal - December 2008 - A Remote Java RMI Registry (Page 39) Dr. Dobb's Journal - December 2008 - Beyond B-Trees (Page 40) Dr. Dobb's Journal - December 2008 - Beyond B-Trees (Page 41) Dr. Dobb's Journal - December 2008 - File Descriptors and Multithreaded Programs (Page 42) Dr. Dobb's Journal - December 2008 - File Descriptors and Multithreaded Programs (Page 43) Dr. Dobb's Journal - December 2008 - File Descriptors and Multithreaded Programs (Page 44) Dr. Dobb's Journal - December 2008 - File Descriptors and Multithreaded Programs (Page 45) Dr. Dobb's Journal - December 2008 - Effective Concurrency (Page 46) Dr. Dobb's Journal - December 2008 - Effective Concurrency (Page 47) Dr. Dobb's Journal - December 2008 - Effective Concurrency (Page 48) Dr. Dobb's Journal - December 2008 - The Agile Edge (Page 49) Dr. Dobb's Journal - December 2008 - The Agile Edge (Page 50) Dr. Dobb's Journal - December 2008 - The Agile Edge (Page 51) Dr. Dobb's Journal - December 2008 - Swaine's Flames (Page 52) Dr. Dobb's Journal - December 2008 - Swaine's Flames (Page Cover3) Dr. Dobb's Journal - December 2008 - Swaine's Flames (Page Cover4)
For optimal viewing of this digital publication, please enable JavaScript and then refresh the page. If you would like to try to load the digital publication without using Flash Player detection, please click here.