Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Doctrine Optimization

Doctrine Optimization

Anna Filina

May 25, 2011
Tweet

More Decks by Anna Filina

Other Decks in Programming

Transcript

  1. Anna Filina PHP Quebec - user group, organizer ConFoo -

    non for profit Web conference, organizer FooLab Inc. - IT solutions for businesses, founder I write code
  2. Content Doctrine 1.2 optimization Profiling tools Find bad DQL Fix

    bad DQL Doctrine 2.0 Share your DQL concerns
  3. Tools Used Doctrine 1.2 MySQL 5.1 PHP 5.3 Xdebug eZ

    Components (now Zeta Components)
  4. Two queries $query1 = Doctrine::getTable('Invoice') ->createQuery('inv') ->leftJoin('inv.Items.Tags') ->where('inv.number LIKE "%10"')

    ->orderBy('inv.subtotal DESC'); $query2 = Doctrine::getTable('Invoice') ->createQuery('inv') ->leftJoin('inv.Items.Tags');
  5. Execution Time Average ezcDebug timed each query 3x Query 1:

    0.20 sec Query 2: 16.26 sec What’s taking so long?
  6. MySQL or PHP? Query took 0.002 sec in MySQL ~18,000

    objects in PHP Doctrine hydrates results
  7. Hydration Process Create objects Copy properties Reindex results Convert results

    to multi-dimensional arrays/ collections And lots of other good (and slow) things
  8. Count ->leftJoin('inv.Items'); ->addSelect('(SELECT COUNT(*) FROM InvoiceItem item WHERE item.invoice_id =

    inv.id ) AS num_items') $inv[0]->num_items; Using left join: 8.91 sec Using subquery: 2.39 sec
  9. Lazy Loading $invoice->Items[0]->Tags[0]; ->leftJoin('inv.Items.Tags tag') Relations without leftJoin: 0.10 sec

    Relations with leftJoin: 0.02 sec, 5x faster Lazy loading especially bad when iterating
  10. Lazy Loading $inv->Items[] = $item; $invoiceItem = new InvoiceItem(); $invoiceItem->invoice_id

    = $inv->id; $invoiceItem->item_id = $item->id; Using relation: 0.03 sec Using associative entity: 0.00065 sec (~46x faster)
  11. Lessons Learned Limit results Select only what needed Use COUNT

    subqueries where appropriate Use ARRAY hydration when possible Avoid lazy-loading in most cases Also look into database optimization (index columns, de-normalization, storage engine, etc.) This also applies to Doctrine 2.0
  12. Lighter and Faster 1 year of planning, 98% rewrite Independent

    model Faster hydration (3x) New lazy loading techniques Batch processing
  13. Examples $iteratable = $query->iterate(); foreach ($iteratable as $item) {} Hydrate

    the results on-demand in an iteration COUNT(inv.Items) ... GROUP BY inv.Items COUNT relations $item1->persist(); $item2->persist(); $entityManager->flush(); Smart batch saving
  14. Resources Code used in this talk: http://annafilina.com/blog/wp-content/uploads/ doctrine-opt.zip Tips from

    the Doctrine team: http://www.doctrine-project.org/projects/orm/1.2/ docs/manual/improving-performance/en Derick Rethan’s “Profiling PHP Applications” Ligaya Turmelle’s “Optimizing MySQL Essentials”