Rose::DB::Object - High Performance Perl ORM
Posted in perl, orm, rdbo Thu, 01 Jun 2006 21:22:00 GMT
In the area of Perl ORM (object relational mappers), there are essentially three players: Class::DBI, DBIx::Class and Rose::DB::Object. Of the three, Rose::DB::Object (a.k.a. RDBO) is known to be the fastest, running just 2-4 times the speed of straight DBI in many tests (albeit using an unloaded database). DBIx::Class is known as the most extensible and flexible. Class::DBI is considered outdated (e.g. it doesn't support JOINs) and to be avoided by many. RDBO is the fastest because speed is it's primary design consideration, implementing many perl and DBI-level optimizations. The design philosophy is described as:
Basically, any work that can be done "up-front" (or at least "infrequently") is done in order to keep the frequently used runtime code path very tight. - John Siracusa
RDBO's implementation accomplishes this feat in several ways:
- aggressive code inlining: method calls can be very expensive and RDBO goes to great lenghts to avoid this. The get_objects method in Rose::DB::Object:Manager is 2129 lines long.
- extensive caching of "derived metadata", e.g. commonly used SQL query strings, column lists, etc.
- extensive use of "the 'fast path' in DBI, such as always using bind_col() and fetch() to retrieve data instead of fetchrow_array(), unbound calls to fetchrow_arrayref(), or fetchrow_hashref()."
- "compiling down" accessor and mutator methods, both with and without triggers, to an optimized form in order to shorten the code path.
Achieving this high performance has resulted in some compromises. They include:
- the code is harder to maintain and extend, resulting in a smaller community of contributors.
- aggregate functions and other queries that do not return table rows (e.g. GROUP BY, HAVING, etc.) are not natively supported yet. A previous entry, Rose::DB::Object - aggregates, describes how to implement aggregates with RDBO.
Perl has a TIMTOWTDI tradition and ORMs are no exception. The primary alternative, DBIx::Class, is designed with extensibility as it's primary consideration and addresses the compromises RDBO has made. The implementation gives up some perl execution speed to RDBO to gain this extensibility while generating roughly equivalent SQL for a similar database load. Both RDBO and DBIC are much faster than Class::DBI. The extensibility philosophy has resulted in an alternative ORM that is more flexible, supports aggregate functions and has a larger community of committers relative to RDBO.
RDBO should be a strong contender if you want the fastest Perl ORM and can accept the design decisions it has made to achieve that performance. If you would like some extra capability and can give up some perl execution speed in your web nodes, it may be worthwhile to evaluate some alternatives.