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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  8. Luís Cobucci

    @lcobucci

    View full-size 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 full-size slide

  10. Our software
    Cache
    External API

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size 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 full-size 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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size 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 full-size 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 full-size 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 full-size 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 full-size 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 full-size slide

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

    View full-size 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 full-size 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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size 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 full-size 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 full-size slide

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

    View full-size slide

  37. SELECT consumer FROM Consumer consumer;

    View full-size 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 full-size slide

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

    View full-size slide

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

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

    ->setParameter('user', 1)

    ->getSingleScalarResult();

    View full-size 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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  46. EntityManager UnitOfWork DB

    View full-size slide

  47. EntityManager UnitOfWork L2C
    DB

    View full-size slide

  48. /**

    * @ORM\Entity

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

    */
    class Consumer

    {

    // …

    }

    View full-size slide

  49. /**

    * @ORM\Entity

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

    */
    class Consumer

    {

    // …

    }
    READ_ONLY

    NONSTRICT_READ_WRITE

    READ_WRITE

    View full-size slide

  50. /**

    * @ORM\Entity

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

    */
    class Message

    {

    // …


    /**

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

    private $consumer;

    // …

    }

    View full-size slide

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

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

    ->setParameter('user', 1)

    ->setCacheable(true)

    ->getResult();

    View full-size slide

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

    View full-size slide

  53. Demystifying
    Luís Cobucci

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

    View full-size slide

  54. Thanks!
    @lcobucci

    View full-size slide