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

Demystifying cache in Doctrine ORM

Luís Cobucci
September 21, 2017

Demystifying cache in Doctrine ORM

Applications should be fast regardless of any cache system. However, sometimes we do need to cache data in order to optimise things and deliver a fast response to the clients.
This talk covers the different types of cache offered Doctrine ORM (metadata, query, result set, and second level cache), how they work together with the Unit of Work and what we should know before caching all the things.

Luís Cobucci

September 21, 2017
Tweet

More Decks by Luís Cobucci

Other Decks in Technology

Transcript

  1. Demystifying
    Luís Cobucci

    @lcobucci
    https://goo.gl/oZPuRc
    cache in Doctrine ORM

    View Slide

  2. Reliability
    https://goo.gl/1shwsY

    View Slide

  3. Maintainability
    https://goo.gl/D4DvKC

    View Slide

  4. Scalability
    https://goo.gl/M67mS8

    View Slide

  5. Trade-offs
    https://goo.gl/L7YdSp

    View Slide

  6. Minions of users!
    https://goo.gl/7MAkHZ

    View Slide

  7. “ There are two hard things in
    Computer Science: cache invalidation,
    naming things, and off-by-one errors
    Common sense

    View Slide

  8. Luís Cobucci

    @lcobucci

    View Slide

  9. “ a hardware or software component
    that stores data so future requests for
    that data can be served faster; the data
    stored in a cache might be the result of
    an earlier computation, or the duplicate
    of data stored elsewhere.
    Cache (computing) - Wikipedia

    View Slide

  10. Our software
    Cache
    External API

    View Slide

  11. Our software
    Cache
    External API
    1. Give me
    “external.result”

    View Slide

  12. Our software
    Cache
    External API
    2. Cache miss
    1. Give me
    “external.result”

    View Slide

  13. Our software
    Cache
    External API
    2. Cache miss
    3. Give me
    data
    1. Give me
    “external.result”

    View Slide

  14. Our software
    Cache
    External API
    2. Cache miss
    3. Give me
    data
    4. There you
    go
    1. Give me
    “external.result”

    View Slide

  15. Our software
    Cache
    External API
    2. Cache miss
    1. Give me
    “external.result”
    3. Give me
    data
    4. There you
    go
    5. Store
    “external.result”

    View Slide

  16. Our software
    Cache
    External API
    2. Cache miss
    1. Give me
    “external.result”
    3. Give me
    data
    4. There you
    go
    5. Store
    “external.result” 6. Stored!

    View Slide

  17. Our software
    Cache
    External API
    1. Give me
    “external.result”

    View Slide

  18. Our software
    Cache
    External API
    2. Cache hit!
    1. Give me
    “external.result”

    View Slide

  19. Doctrine ORM?
    https://goo.gl/xCBz84

    View Slide

  20. Template
    Message
    Consumer
    Campaign
    1
    1
    1
    *
    *
    *

    View Slide

  21. Template
    Message
    Consumer
    Campaign
    1
    1
    1
    *
    *
    *

    View Slide

  22. Template
    Message
    Consumer
    Campaign
    1
    1
    1
    *
    *
    *
    Order
    matters

    View Slide

  23. Template
    Message
    Consumer
    Campaign
    1
    1
    1
    *
    *
    *
    INSERT INTO consumer (name, email)

    VALUES (“Luís Cobucci”, “[email protected]”);

    SET @consumer_id = LAST_INSERT_ID();

    View Slide

  24. Template
    Message
    Consumer
    Campaign
    1
    1
    1
    *
    *
    *
    INSERT INTO consumer (name, email)

    VALUES (“Luís Cobucci”, “[email protected]”);

    SET @consumer_id = LAST_INSERT_ID();
    INSERT INTO template (name, body)

    VALUES (“Template 1”, “blah… blah… blah…”);

    View Slide

  25. Template
    Message
    Consumer
    Campaign
    1
    1
    1
    *
    *
    *
    INSERT INTO consumer (name, email)

    VALUES (“Luís Cobucci”, “[email protected]”);

    SET @consumer_id = LAST_INSERT_ID();
    INSERT INTO template (name, body)

    VALUES (“Template 1”, “blah… blah… blah…”);
    INSERT INTO campaign (title, template_id, message)

    VALUES (“Test”, LAST_INSERT_ID(), “blah… blah… blah…”);

    View Slide

  26. Template
    Message
    Consumer
    Campaign
    1
    1
    1
    *
    *
    *
    INSERT INTO consumer (name, email)

    VALUES (“Luís Cobucci”, “[email protected]”);

    SET @consumer_id = LAST_INSERT_ID();
    INSERT INTO template (name, body)

    VALUES (“Template 1”, “blah… blah… blah…”);
    INSERT INTO campaign (title, template_id, message)

    VALUES (“Test”, LAST_INSERT_ID(), “blah… blah… blah…”);
    INSERT INTO message (campaign_id, consumer_id, sent)

    VALUES (LAST_INSERT_ID(), @consumer_id, FALSE);

    View Slide

  27. Template
    Message
    Consumer
    Campaign
    1
    1
    1
    *
    *
    *
    INSERT INTO consumer (name, email)

    VALUES (“Luís Cobucci”, “[email protected]”);

    SET @consumer_id = LAST_INSERT_ID();
    INSERT INTO template (name, body)

    VALUES (“Template 1”, “blah… blah… blah…”);
    INSERT INTO campaign (title, template_id, message)

    VALUES (“Test”, LAST_INSERT_ID(), “blah… blah… blah…”);
    INSERT INTO message (campaign_id, consumer_id, sent)

    VALUES (LAST_INSERT_ID(), @consumer_id, FALSE);
    Don’t forget to use a
    transaction!

    View Slide

  28. EntityManager
    persist()
    flush()
    find()
    remove()

    View Slide

  29. declare(strict_types=1);
    $consumer = new Consumer('Luís Cobucci', '[email protected]');

    $template = new Template('Template 1', 'blah… blah… blah…');

    $campaign = new Campaign($template, 'Test', 'blah… blah… blah…');

    $message = new Message($campaign, $consumer, false);


    $entityManager->persist($consumer);
    $entityManager->persist($template);
    $entityManager->persist($campaign);
    $entityManager->persist($message);
    $entityManager->flush();

    View Slide

  30. declare(strict_types=1);
    $consumer = $entityManager->find('Consumer', 2);
    $campaign = $entityManager->find('Campaign', 1);


    $message = new Message($campaign, $consumer, false);


    $entityManager->persist($message);
    $entityManager->flush();

    View Slide

  31. http://goo.gl/gH0hsx
    Amazing, right?

    View Slide

  32. Make it fast!
    https://goo.gl/6Y2kQd

    View Slide

  33. Metadata
    https://goo.gl/AhjBFJ

    View Slide

  34. /** @ORM\Entity */
    class Consumer

    {

    /** 

    * @ORM\Id

    * @ORM\GeneratedValue 

    * @ORM\Column(type="integer")

    */
    private $id;


    /** @ORM\Column(type="string") */

    private $name;


    /** @ORM\Column(type="string") */

    private $email;
    }

    View Slide

  35. /** @ORM\Entity */
    class Consumer

    {

    /** 

    * @ORM\Id

    * @ORM\GeneratedValue 

    * @ORM\Column(type="integer")

    */
    private $id;


    /** @ORM\Column(type="string") */

    private $name;


    /** @ORM\Column(type="string") */

    private $email;
    }
    ClassMetadata

    View Slide

  36. Query
    https://goo.gl/nuFRba

    View Slide

  37. SELECT consumer FROM Consumer consumer;

    View Slide

  38. SELECT consumer FROM Consumer consumer;
    SELECT

    c0.id AS id_0,

    c0.name AS name_1,
    c0.email AS email_2,

    FROM consumer c0;

    View Slide

  39. Result set
    https://goo.gl/7yah7S

    View Slide

  40. $query = 'SELECT COUNT(m) FROM Message m WHERE m.user = :user';

    $count = $entityManager->createQuery($query)

    ->setParameter('user', 1)

    ->getSingleScalarResult();

    View Slide

  41. $query = 'SELECT COUNT(m) FROM Message m WHERE m.user = :user';

    $count = $entityManager->createQuery($query)

    ->setParameter('user', 1)

    ->useResultCache(true)

    ->useResultCacheLifeTime(3600)

    ->getSingleScalarResult();

    View Slide

  42. L2C
    https://goo.gl/8pbG3y

    View Slide

  43. https://goo.gl/cuLYT9
    Bugs…

    View Slide

  44. https://goo.gl/1y3fvm
    Bugs…

    View Slide

  45. https://goo.gl/D3Gw7e
    Bugs…

    View Slide

  46. EntityManager UnitOfWork DB

    View Slide

  47. EntityManager UnitOfWork L2C
    DB

    View Slide

  48. /**

    * @ORM\Entity

    * @ORM\Cache(usage="NONSTRICT_READ_WRITE")

    */
    class Consumer

    {

    // …

    }

    View Slide

  49. /**

    * @ORM\Entity

    * @ORM\Cache(usage="NONSTRICT_READ_WRITE")

    */
    class Consumer

    {

    // …

    }
    READ_ONLY

    NONSTRICT_READ_WRITE

    READ_WRITE

    View Slide

  50. /**

    * @ORM\Entity

    * @ORM\Cache(usage="NONSTRICT_READ_WRITE")

    */
    class Message

    {

    // …


    /**

    * @ORM\ManyToOne(targetEntity="Consumer")
    * @ORM\Cache(usage="READ_ONLY")
    */

    private $consumer;

    // …

    }

    View Slide

  51. $query = ‘SELECT m FROM Message m WHERE m.user = :user';

    $messages = $entityManager->createQuery($query)

    ->setParameter('user', 1)

    ->setCacheable(true)

    ->getResult();

    View Slide

  52. https://goo.gl/bGP8u8
    Intense traffic

    View Slide

  53. Demystifying
    Luís Cobucci

    @lcobucci
    https://goo.gl/oZPuRc
    cache in Doctrine ORM

    View Slide

  54. Thanks!
    @lcobucci

    View Slide