5

I have just been testing the performance Eloquent ORM in Laravel and was shocked to find a simple query taking over 3 seconds to perform compared to the normal Laravel query which finished in 0.1 seconds. I'm only returning 1500 records.

DB::table('t_organisations')->get();  -  0.12253594398499 seconds
Organisation::all();   -   3.6389181613922 seconds

Surely this can't be normal!? I don't think I have missed anything in the setup. My db is normalized. What could be the problem?

Craig Morgan
  • 910
  • 1
  • 10
  • 24
  • Personally, I'd run it trough XDebug to see where the time waste is. – Alexandre Danault Jul 09 '13 at 12:01
  • 1
    Do you have any relationships defined in your model? If so - Eloquent would need to do lots of joins... – Laurence Jul 09 '13 at 12:03
  • There's always thing that are best to use Query Builder especially when handling large data. – crynobone Jul 09 '13 at 12:23
  • 3
    Turn on your mysql query log and see if more queries are being done via the ORM vs query builder. Additionally, run that test many times to see if the speed difference remains the same - as with any speed test, other factors are usually mucking up the results. Curious to see what you find! – fideloper Jul 09 '13 at 12:39
  • which tool are you using to test this ? – Jeff Aug 30 '17 at 16:24

3 Answers3

5

When you do DB::table('t_organisations')->get(); It fetches all results as an array (or objects) but does not hydrate them to the model. See this stackoverflow answer if you want a quick explanation.

When you do Organisation::all(); The hydration process takes place, which is why the request takes longer (you have to allocate all objects in the memory and fill them with the fields). There are many links/tuts on hydration optimization to help you better request your database, and avoid the hydration of objects when you don't need it.

Community
  • 1
  • 1
hilnius
  • 2,049
  • 2
  • 15
  • 28
2

Thanks for all your replies.

Here's the result of the mysql query log:

Organisation::all(); - 1.6772060394287 secs

130710  9:52:43     5 Connect   seltec@localhost on seltec
            5 Prepare   set names 'utf8' collate 'utf8_unicode_ci'
            5 Execute   set names 'utf8' collate 'utf8_unicode_ci'
            5 Close stmt    
            5 Prepare   select * from `users` where `id` = ? limit 1
            5 Execute   select * from `users` where `id` = '2' limit 1
            5 Close stmt    
            5 Prepare   select * from `t_organisations`
            5 Execute   select * from `t_organisations`
130710  9:52:44     5 Close stmt    
130710  9:52:45     5 Quit

DB::table('t_organisations')->get(); - 0.13963603973389 secs

130710  9:55:16     6 Connect   seltec@localhost on seltec
            6 Prepare   set names 'utf8' collate 'utf8_unicode_ci'
            6 Execute   set names 'utf8' collate 'utf8_unicode_ci'
            6 Close stmt    
            6 Prepare   select * from `users` where `id` = ? limit 1
            6 Execute   select * from `users` where `id` = '2' limit 1
            6 Close stmt    
            6 Prepare   select * from `t_organisations`
            6 Execute   select * from `t_organisations`
            6 Close stmt    
            6 Quit

So no difference there then.... which means the delay must lie in the Eloquent php code. Yes, I have xdebug installed and no I am not prepared to waste my time trying to figure out why it's slow!!! If it's faster in query builder, that's good enough for me!!

@Laravels' developers: great job on the framework. It's intuitive, deals with authorizations well, especially with the confide and entrust plugins from Leroy Merlin. You might want to have a look at the Eloquent performance issue though!!

Cheers! Craig

Craig Morgan
  • 910
  • 1
  • 10
  • 24
  • What do you mean Leroy Merlin? Entrust and Confide were written by Zizaco [link](https://github.com/Zizaco/confide) – Thomas Clarkson Jul 10 '13 at 09:15
  • Eloquent sits on top of Query Builder, parsing the data it returns into class instances. This will always be slower than using just Query Builder. You can cache Eloquent results with: "Organisation::all()->remember(5);". – assertchris Aug 26 '13 at 10:12
2

Make sure to do a RESET QUERY CACHE to clear your MySQL query cache in between tests. From the timestamps you posted it looks like you did the Eloquent queries first, which means that they were probably cached by the time you did the second test. That would explain the huge performance differential, although I do suspect Eloquent to be a little bit slower than normal Laravel queries because of the additional overhead.

wizardjoe
  • 151
  • 5