Talks

Eager Loading for ActiveRecord Performance

Dinah is wrapping up her engineering degree at the University of Waterloo. In 2017, she spent four months backpacking around Europe and China while looking for half-decent WIFI connections to power her open-source contributions. For the last few months, she has been building a public API to expose more preloading options in Ruby on Rails.

Balkan Ruby 2018

00:00:13.200 Hello everyone! My name is Dinah Shi. You can find me on Twitter and GitHub at dynasty. I am not actually from Toronto, but I flew here, and one of the speakers tomorrow might tell you how that ended up happening. I have been an infrequent contributor to Active Record as well as other parts of Ruby on Rails.
00:00:27.250 Today, we're going to be talking about eager loading, specifically different options for loading associations with an emphasis on performance. If you were at RailsConf this past year or have seen the published videos, you may have seen DHH, the creator of Ruby on Rails, deliver a keynote.
00:00:40.680 In his talk, he discussed a concept called "conceptual compression." This is the process of going from low-level technical details to higher-level concepts. If you are intrigued by this topic, I would recommend checking out his talk. In essence, going to low-level stuff like assembly language and memory management allows for highly customized systems based on your application’s needs. High-level concepts like Rails let you focus on business logic without worrying too much about the underlying details.
00:01:04.750 One of the great aspects of conceptual compression is that it lowers the barrier to entry for programming. It helps more people discover this wonderful world of technology and everything it can do. This is one of the reasons I'm excited about contributing to Ruby on Rails.
00:01:30.750 In his keynote, DHH also alluded to Active Record, which is crucial because it encapsulates everything you need to know about databases to build a web application. To ensure we're all on the same page, I want to clarify what Active Record is.
00:01:57.920 Active Record is defined as a technique for converting data between incompatible type systems to create a virtual object database. Essentially, it serves as the interface between your database and your application’s language, whether that's Ruby or another language. Active Record is the ORM you get out of the box with Rails, but it's also designed to work as a standalone module.
00:02:31.819 Active Record was first coined by Martin Fowler in his book "Patterns of Enterprise Application Architecture.” He describes it as an object that wraps a row in a database table or view and encapsulates the database access and logic.
00:02:50.790 Active Record connects to your underlying database and maps to a row in that table, with methods like create and update. It holds properties that correspond to the table’s columns.
00:03:07.810 Active Record works efficiently because, about 10 to 15 years ago, many web developers were writing a lot of SQL queries manually. Nowadays, if you use Active Record or another ORM, you may not have to write SQL queries very often.
00:03:30.270 This is great as it allows you to stay within Ruby without switching back and forth between different languages, but sometimes it can lead to performance issues. You may not realize how many queries are being run for a particular page load or endpoint.
00:03:48.660 One common issue among Active Record developers is the N+1 query problem, which starts when you query an association model. A typical example could be a blog, where a post has many comments. When you load posts and then subsequently load their comments, you may end up running one query for posts and then N queries for the comments. This results in an inefficient use of resources.
00:04:53.730 A recommended solution for this issue is to uses the `includes` method that Active Record provides. By using `includes`, you can tell Active Record to fetch the associated objects alongside the main query, thus preventing the N+1 query scenario.
00:05:18.750 However, it's essential to understand when to use these methods because while `includes` can enhance performance, it can also lead to larger queries if not managed correctly. Queries can take longer to execute if your underlying database gets overloaded.
00:05:49.750 We need to understand how Active Record can optimize these calls and what options are available to us when querying. Let's tackle relations in Active Record, as they play a crucial role in how we work with associations.
00:06:01.609 Relations in Active Record are essentially a representation of queries. When you're building relations, no actual queries are executed until you attempt to enumerate over the returned objects, although the underlying query is being built up. This lazy execution model allows for improved performance.
00:06:30.770 We can reason further about how Active Record implements eager loading with the includes method. The way it works is related to how SQL handles JOIN commands and the underlying database structure.
00:06:58.990 When we use the `includes` method, we are effectively optimizing how we load associations and preventing excessive queries. The end result leads to a more performant application if done correctly.
00:07:27.779 Additionally, while eager loading and includes help tackle performance issues, it is important to note that memory consumption could spike, especially if you're using multiple associations.
00:07:49.990 In cases where memory is critical, alternative solutions like counter caches can be beneficial. A counter cache keeps track of the number of comments but does not load all objects into memory, allowing the application to remain responsive.
00:08:13.000 Another useful technique is Russian doll caching or fragment caching, often preferred in Rails applications to optimize data rendering and reduce load times.
00:08:32.990 It's vital, however, to determine the best caching strategy for your specific application, including understanding when to apply eager loading, counter caching, and fragment caching.
00:08:56.330 In conclusion, there isn't one definitive solution to performance issues. Each application's requirements and architecture will lead you to choose different strategies. Performance optimization is an ongoing process in software development.
00:09:16.050 Therefore, leverage the power of tools to profile your application and pinpoint where the bottlenecks exist. Always be prepared to adapt your approach based on outcomes and performance metrics.
00:09:37.650 With that being said, I will be available for any further discussions after the talk, and I hope to see you applying these concepts in your own Rails applications for improved performance.
00:09:55.950 Thank you!