Doctrine 2 is not slow!*
*if you know how to use it and configure it correctly
A certain bad habit is spreading around here. From time to time someone shows up with the claim that Doctrine is slow and therefore unusable on real projects. This misconception stems from several myths that Doctrine 2 is shrouded in.
As I wrote three and a half years ago, the main motivation for using an ORM is representing data from the database in the application through consistent objects. Objects that are not generic universal hashmaps with unknown contents, but objects that have a fixed, well-defined interface and therefore I know what data I can get from them and how to manipulate it. So I don’t want the ORM to save me from writing SQL queries, and I don’t even want to be shielded from the specific database I’m using. I can therefore afford to optimize data retrieval very much like with other „lightweight“ libraries which, according to the malicious tongues linked above, are no longer slow.
So if I want a high-performance application, I don’t leave most SQL queries to be generated by Doctrine, but write them myself using DQL, which is a related language that Doctrine uses. Instead of tables of columns, in it you reference entity classes and attributes. It’s easily extensible, which comes in handy if you need to use some feature of your database that DQL doesn’t support out of the box.
In case I want to select data from the database for reading only (typically for output in a template), there’s no need to transfer whole objects. In that case I list the columns I’m interested in within DQL, and Doctrine returns the query result to me in plain arrays. Thanks to DQL you can also avoid the 1+N problem (lazy loading inside a loop). However, above a certain traffic level you can’t afford to keep reaching for fresh data from the database with any tool, and you have to deploy application-level caching either way.
Doctrine’s opponents often argue that it’s a behemoth. I’m not sure what exactly they mean by that. They probably don’t like that its source is spread across many files, and they find the approach of mPDF far more appealing. In any case, though, the size of the library has no impact on performance if you enable and correctly configure OpCache, which significantly eases PHP’s workload.
Furthermore, in production you should disable automatic generation of proxy classes:
$config->setAutoGenerateProxyClasses(FALSE);
Otherwise Doctrine will generate a proxy for every entity on every request, which is, yes, slow.[1]
You should also set up a cache for metadata (entity configuration) and compiled DQL queries. See the list of all available drivers.
$cache = new \Doctrine\Common\Cache\ApcCache();
$config->setMetadataCacheImpl($cache);
$config->setQueryCacheImpl($cache);
You can verify the correctness of these settings with the CLI command orm:ensure-production-settings.
The worst idea you can get is to write your own ORM. It’s an incredibly complex and demanding area. The problems you’ll be solving were solved long ago by Doctrine’s authors. But if you have two years to develop your own ORM full-time and think you can do it better than they did, I won’t stop you.
Proxy classes serve for lazy loading of associated data – Doctrine generates code that, when an unloaded property is accessed, issues a query to the database. ↩︎