ORM                            Database                          Developers      http://www.flickr.com/photos/hoyvinmayvin/...
ORMs donʼt kill your DB, developers do!               @guilhermeblanco               http://github.com/guilhermeblanco    ...
Agenda      http://www.flickr.com/photos/emerzh/3072428824/Thursday, March 1, 2012
General Rule           RTFMThursday, March 1, 2012
Dependency management      http://www.flickr.com/photos/ollesvensson/3694625903/Thursday, March 1, 2012
Dependency ManagementThursday, March 1, 2012
Dependency Management                          namespace AppBundleBlogBundleEntity;                          /**          ...
Dependency ManagementThursday, March 1, 2012
Dependency ManagementThursday, March 1, 2012
Dependency Management                          namespace AppBundleBlogBundleEntity;                          /**          ...
Fetch Mode      http://www.flickr.com/photos/comedynose/5318259802/Thursday, March 1, 2012
Fetch Mode         A fetching strategy is what ORM will use to retrieve        associated objects if the application needs...
Fetch Mode                          Supported by all association types...Thursday, March 1, 2012
Fetch Mode     • OneToOne     • OneToMany     • ManyToOne     • ManyToManyThursday, March 1, 2012
Fetch Mode                          Available fetch modes...Thursday, March 1, 2012
Fetch Mode     • EAGER     • LAZY (default)     • EXTRA_LAZYThursday, March 1, 2012
Fetch Mode                An association (collection or attribute), is               fetched immediately when owner is loa...
Fetch Mode                An association (collection or attribute), is               fetched immediately when owner is loa...
Fetch Mode                An association (collection or attribute), is               fetched immediately when owner is loa...
Fetch Mode                          /**                           * @ORMEntity                           */               ...
Fetch Mode                          /**                           * @ORMEntity                           */               ...
Querying      http://www.flickr.com/photos/pschadler/4932737690/Thursday, March 1, 2012
Querying                          $query    = $entityManager->createQuery(                              SELECT p          ...
Querying                          $query    = $entityManager->createQuery(                              SELECT p          ...
Querying                          $query    = $entityManager->createQuery(                              SELECT p, t       ...
Querying                          $query    = $entityManager->createQuery(                              SELECT p, t       ...
Querying                          I know you all don’t trust me...Thursday, March 1, 2012
Querying                          ...but take a look at its EBNF grammar...Thursday, March 1, 2012
QueryLanguage                                ::=   SelectStatement | UpdateStatement | DeleteStatement SelectStatement    ...
Querying         Since the letter size is 6, you may still not believe meThursday, March 1, 2012
Querying                          let’s try a real world example!Thursday, March 1, 2012
Querying                          Do you know Facebook activity wall?Thursday, March 1, 2012
Querying                          Do you know Facebook activity wall?                                    Let’s show it!Thu...
SELECT  e, a   FROM  Entry e   JOIN  e.wall w   JOIN  e.user u   LEFT  JOIN u.avatar av  WHERE  u = :user     OR  w IN (  ...
SELECT  e, a   FROM  Entry e   JOIN  e.wall w           Entry you wrote   JOIN  e.user u   LEFT  JOIN u.avatar av  WHERE  ...
SELECT  e, a   FROM  Entry e   JOIN  e.wall w           Entry you wrote   JOIN  e.user u   LEFT  JOIN u.avatar av  WHERE  ...
SELECT  e, a   FROM  Entry e   JOIN  e.wall w           Entry you wrote   JOIN  e.user u   LEFT  JOIN u.avatar av  WHERE  ...
SELECT  e, a   FROM  Entry e   JOIN  e.wall w           Entry you wrote   JOIN  e.user u   LEFT  JOIN u.avatar av  WHERE  ...
Caching      http://www.flickr.com/photos/eszter/3851576235/Thursday, March 1, 2012
Caching                          Doctrine supports 3 levels of caching...Thursday, March 1, 2012
Caching     • Metadata cache     • Query cache     • Result cacheThursday, March 1, 2012
Caching                      Cache mapping of entities     • Metadata cache     • Query cache     • Result cacheThursday, ...
Caching                      Cache mapping of entities     • Metadata cache     • Query cache                     Cache DQ...
Caching                      Cache mapping of entities     • Metadata cache     • Query cache                       Cache ...
Caching                    $query   = $entityManager->createQuery(                        SELECT p                        ...
Indexing      http://www.flickr.com/photos/osuarchives/2659419894/Thursday, March 1, 2012
Indexing         Doctrine is able to hint the Schema Tool to generate            database indexes on specified table column...
Indexing                          /**                           * @ORMEntity                           * @ORMTable(       ...
Indexing                          @ORMUniqueConstraint(                              name    = "user_unique",             ...
Indexing                  @ORMIndex(                      name    = "login_idx",                       columns = { "name",...
Indexing                  @ORMIndex(                      name    = "login_idx",                       columns = { "name",...
Inheritance      http://www.flickr.com/photos/duanekeys/307005468/Thursday, March 1, 2012
Inheritance                          Inheritance is a very deep topic in ORMsThursday, March 1, 2012
Inheritance      Each inheritance type has advantages and disadvantagesThursday, March 1, 2012
Inheritance     • Concrete Table Inheritance     • Single Table Inheritance     • Class Table InheritanceThursday, March 1...
Inheritance               One Class, one Table     • Concrete Table Inheritance     • Single Table Inheritance     • Class...
Inheritance               One Class, one Table     • Concrete Table Inheritance     • Single Table Inheritance Multiple Cl...
Inheritance               One Class, one Table     • Concrete Table Inheritance     • Single Table Inheritance Multiple Cl...
Inheritance     • Concrete Table InheritanceThursday, March 1, 2012
Inheritance     • Concrete Table Inheritance           •      ProsThursday, March 1, 2012
Inheritance     • Concrete Table Inheritance           •      Pros                 •        No locking problemsThursday, M...
Inheritance     • Concrete Table Inheritance           •      Pros                 •        No locking problems           ...
Inheritance     • Concrete Table Inheritance           •      Pros                 •        No locking problems           ...
Inheritance     • Concrete Table Inheritance           •      Pros                 •        No locking problems           ...
Inheritance     • Concrete Table Inheritance           •      Pros                 •        No locking problems           ...
Inheritance     • Concrete Table Inheritance           •      Pros                 •        No locking problems           ...
Inheritance                          /**                           * @ORMMappedSuperclass                           */    ...
Inheritance             CREATE TABLE users (                 id INTEGER AUTO_INCREMENT NOT NULL,                 firstName...
Inheritance     • Single Table InheritanceThursday, March 1, 2012
Inheritance     • Single Table Inheritance           •      ProsThursday, March 1, 2012
Inheritance     • Single Table Inheritance           •      Pros                 •        Only one table for hierarchyThur...
Inheritance     • Single Table Inheritance           •      Pros                 •        Only one table for hierarchy    ...
Inheritance     • Single Table Inheritance           •      Pros                 •        Only one table for hierarchy    ...
Inheritance     • Single Table Inheritance           •      Pros                 •        Only one table for hierarchy    ...
Inheritance     • Single Table Inheritance           •      Pros                 •        Only one table for hierarchy    ...
Inheritance     • Single Table Inheritance           •      Pros                 •        Only one table for hierarchy    ...
Inheritance     • Single Table Inheritance           •      Pros                 •        Only one table for hierarchy    ...
Inheritance                          namespace MyAppEntity;                          /**                           * @ORME...
Inheritance                   CREATE TABLE people (                       id INT AUTO_INCREMENT NOT NULL,                 ...
Inheritance     • Class Table InheritanceThursday, March 1, 2012
Inheritance     • Class Table Inheritance           •      ProsThursday, March 1, 2012
Inheritance     • Class Table Inheritance           •      Pros                 •        Easy to understandThursday, March...
Inheritance     • Class Table Inheritance           •      Pros                 •        Easy to understand               ...
Inheritance     • Class Table Inheritance           •      Pros                 •        Easy to understand               ...
Inheritance     • Class Table Inheritance           •      Pros                 •        Easy to understand               ...
Inheritance     • Class Table Inheritance           •      Pros                 •        Easy to understand               ...
Inheritance     • Class Table Inheritance           •      Pros                 •        Easy to understand               ...
Inheritance     • Class Table Inheritance           •      Pros                 •        Easy to understand               ...
Inheritance                          namespace MyAppEntity;                          /**                           * @ORME...
Inheritance                          CREATE TABLE users (                              id INT AUTO_INCREMENT NOT NULL,    ...
Inheritance                          What’s the problem with inheritance?Thursday, March 1, 2012
Inheritance                          What’s the problem with inheritance?                                       HydrationT...
InheritanceThursday, March 1, 2012
Inheritance     • Inverse side *ToOneThursday, March 1, 2012
Inheritance     • Inverse side *ToOne     • Owning side *ToOne with InheritanceThursday, March 1, 2012
Inheritance     • Inverse side *ToOne     • Owning side *ToOne with Inheritance     • Disabled deferEagerLoad while Queryi...
Cascades      http://www.flickr.com/photos/over_kind_man/3158552109/Thursday, March 1, 2012
Cascades Ability to tell Unit Of Work of Doctrine how it should act      when inspecting an association for graph changesT...
Cascades                          Use judiciouslyThursday, March 1, 2012
Cascades       It can heavily increase the graph edges to be navigated            once the Compute Changeset algorithm is ...
Cascades                                 This means more time to                          persist, delete, merge, detach, ...
Cascades                          /**                           * @ORMEntity                           */                 ...
Hydrators      http://crimsonnightstock.deviantart.com/art/Yellow-Fire-Hydrant-Stock-100121929Thursday, March 1, 2012
Hydrators            Doctrine comes with some useful result hydratorsThursday, March 1, 2012
Hydrators This means that not all times you need to retrieve objectsThursday, March 1, 2012
Hydrators     • Object     • Array     • Scalar     • Iterable     • Simple Object     • Single ScalarThursday, March 1, 2...
Hydrators     •      Object        $resultList = $query->getResult();     • Array     • Scalar     • Iterable     • Simple...
Hydrators     •      Object           $resultList = $query->getResult();     • Array              $resultArray = $query->g...
Hydrators     •      Object           $resultList = $query->getResult();     • Array              $resultArray = $query->g...
Hydrators     •      Object           $resultList = $query->getResult();     • Array              $resultArray = $query->g...
Hydrators     •      Object           $resultList = $query->getResult();     • Array              $resultArray = $query->g...
Hydrators     •      Object           $resultList = $query->getResult();     • Array              $resultArray = $query->g...
http://joind.in/6053                                       Questions?           @guilhermeblanco           http://github.c...
http://joind.in/6053                                        Questions?           @guilhermeblanco           http://github....
http://joind.in/6053                                        Questions?                                        Thank you!  ...
Upcoming SlideShare
Loading in...5
×

ORM dont kill your DB, developers do

8,127

Published on

Presentation gave at ConFoo 2012 (2012-03-01)

As soon as you decide to use an ORM tool, one of the biggest factors is Rapid Application Development.
Everything is wonderful during development phase, but when it hits production, performance doesn't work like you expect.
You may think it's ORM's fault, your expected it to write as efficient queries as you manually do, but like guns, ORMs don't kill your database, developers do!
This talk will go deep into Doctrine 2 ORM by exploring performance tips that can save your application from its deepest nightmare.

Published in: Technology

ORM dont kill your DB, developers do

  1. 1. ORM Database Developers http://www.flickr.com/photos/hoyvinmayvin/5103806609/ Guilherme BlancoThursday, March 1, 2012
  2. 2. ORMs donʼt kill your DB, developers do! @guilhermeblanco http://github.com/guilhermeblanco InstaClick Inc. Learning about good ORM practices on @guilhermeblanco talk at @confooca!Thursday, March 1, 2012
  3. 3. Agenda http://www.flickr.com/photos/emerzh/3072428824/Thursday, March 1, 2012
  4. 4. General Rule RTFMThursday, March 1, 2012
  5. 5. Dependency management http://www.flickr.com/photos/ollesvensson/3694625903/Thursday, March 1, 2012
  6. 6. Dependency ManagementThursday, March 1, 2012
  7. 7. Dependency Management namespace AppBundleBlogBundleEntity; /**  * @ORMEntity  */ class Post {     /**      * @ORMOneToMany(      *   targetEntity="AppComment:Comment",      *   mappedBy="post"      * )      */     protected $comments; } namespace AppBundleCommentBundleEntity; /**  * @ORMEntity  */ class Comment {     /**      * @ORMManyToOne(      *   targetEntity="AppBlog:Post",      *   inversedBy="comments"      * )      */     protected $post; }Thursday, March 1, 2012
  8. 8. Dependency ManagementThursday, March 1, 2012
  9. 9. Dependency ManagementThursday, March 1, 2012
  10. 10. Dependency Management namespace AppBundleBlogBundleEntity; /**  * @ORMEntity  */ class Post {     // ... } namespace AppBundleCommentBundleEntity; /**  * @ORMEntity  */ class Comment {     /**      * @ORMManyToOne(targetEntity="AppBlog:Post")      */     protected $post; }Thursday, March 1, 2012
  11. 11. Fetch Mode http://www.flickr.com/photos/comedynose/5318259802/Thursday, March 1, 2012
  12. 12. Fetch Mode A fetching strategy is what ORM will use to retrieve associated objects if the application needs to navigate through themThursday, March 1, 2012
  13. 13. Fetch Mode Supported by all association types...Thursday, March 1, 2012
  14. 14. Fetch Mode • OneToOne • OneToMany • ManyToOne • ManyToManyThursday, March 1, 2012
  15. 15. Fetch Mode Available fetch modes...Thursday, March 1, 2012
  16. 16. Fetch Mode • EAGER • LAZY (default) • EXTRA_LAZYThursday, March 1, 2012
  17. 17. Fetch Mode An association (collection or attribute), is fetched immediately when owner is loaded • EAGER • LAZY (default) • EXTRA_LAZYThursday, March 1, 2012
  18. 18. Fetch Mode An association (collection or attribute), is fetched immediately when owner is loaded • EAGER An association (collection or attribute), • LAZY (default) is fetched when the application invokes an operation over it • EXTRA_LAZYThursday, March 1, 2012
  19. 19. Fetch Mode An association (collection or attribute), is fetched immediately when owner is loaded • EAGER An association (collection or attribute), • LAZY (default) is fetched when the application invokes an operation over it • EXTRA_LAZY Individual elements from association are accessed from Database as needed. ORM does not fetch the whole association unless it is absolutely necessaryThursday, March 1, 2012
  20. 20. Fetch Mode /**  * @ORMEntity  */ class Post {     /**      * @ORMManyToOne(targetEntity="User", fetchMode="EAGER")      */     protected $author;     /**      * @ORMManyToMany(targetEntity="Tags", fetchMode="EXTRA_LAZY")      * @ORMJoinTable(name="posts_tags")      */     protected $tagList; } /**  * @ORMEntity  */ class Comment {     /**      * @ORMOneToMany(targetEntity="Post", fetchMode="LAZY")      * @JoinColumn(name="post_id", referencedColumnName="id")      */     protected $post; }Thursday, March 1, 2012
  21. 21. Fetch Mode /**  * @ORMEntity  */ Deadly sin class Post {     /**      * @ORMManyToOne(targetEntity="User", fetchMode="EAGER")      */     protected $author;     /**      * @ORMManyToMany(targetEntity="Tags", fetchMode="EXTRA_LAZY")      * @ORMJoinTable(name="posts_tags")      */     protected $tagList; } /**  * @ORMEntity  */ class Comment {     /**      * @ORMOneToMany(targetEntity="Post", fetchMode="LAZY")      * @JoinColumn(name="post_id", referencedColumnName="id")      */     protected $post; }Thursday, March 1, 2012
  22. 22. Querying http://www.flickr.com/photos/pschadler/4932737690/Thursday, March 1, 2012
  23. 23. Querying $query    = $entityManager->createQuery(     SELECT p        FROM Post p ); $postList = $query->getResult(); foreach ($postList as $post) {     $tagList = $post->getTagList();     foreach ($tagList as $tag) {         echo $tag->getName();     } }Thursday, March 1, 2012
  24. 24. Querying $query    = $entityManager->createQuery(     SELECT p        FROM Post p ); $postList = $query->getResult(); foreach ($postList as $post) {     $tagList = $post->getTagList(); N + 1 trolls?     foreach ($tagList as $tag) {         echo $tag->getName();     } }Thursday, March 1, 2012
  25. 25. Querying $query    = $entityManager->createQuery(     SELECT p, t        FROM Post p        LEFT JOIN p.tagList t ); $postList = $query->getResult(); foreach ($postList as $post) {     $tagList = $post->getTagList();     foreach ($tagList as $tag) {         echo $tag->getName();     } }Thursday, March 1, 2012
  26. 26. Querying $query    = $entityManager->createQuery(     SELECT p, t        FROM Post p  Pardon? DQL is       LEFT JOIN p.tagList t ); powerful! RTFM $postList = $query->getResult(); foreach ($postList as $post) {     $tagList = $post->getTagList();     foreach ($tagList as $tag) {         echo $tag->getName();     } }Thursday, March 1, 2012
  27. 27. Querying I know you all don’t trust me...Thursday, March 1, 2012
  28. 28. Querying ...but take a look at its EBNF grammar...Thursday, March 1, 2012
  29. 29. QueryLanguage ::= SelectStatement | UpdateStatement | DeleteStatement SelectStatement ::= SelectClause FromClause [WhereClause] [GroupByClause] [HavingClause] [OrderByClause] UpdateStatement ::= UpdateClause [WhereClause] DeleteStatement ::= DeleteClause [WhereClause] JoinAssociationPathExpression ::= IdentificationVariable "." (CollectionValuedAssociationField | SingleValuedAssociationField) AssociationPathExpression ::= CollectionValuedPathExpression | SingleValuedAssociationPathExpression SingleValuedPathExpression ::= StateFieldPathExpression | SingleValuedAssociationPathExpression StateFieldPathExpression ::= IdentificationVariable "." StateField | SingleValuedAssociationPathExpression "." StateField SingleValuedAssociationPathExpression ::= IdentificationVariable "." SingleValuedAssociationField CollectionValuedPathExpression ::= IdentificationVariable "." {SingleValuedAssociationField "."}* CollectionValuedAssociationField StateField ::= {EmbeddedClassStateField "."}* SimpleStateField SimpleStateFieldPathExpression ::= IdentificationVariable "." StateField SelectClause ::= "SELECT" ["DISTINCT"] SelectExpression {"," SelectExpression}* SimpleSelectClause ::= "SELECT" ["DISTINCT"] SimpleSelectExpression UpdateClause ::= "UPDATE" AbstractSchemaName ["AS"] AliasIdentificationVariable "SET" UpdateItem {"," UpdateItem}* DeleteClause ::= "DELETE" ["FROM"] AbstractSchemaName ["AS"] AliasIdentificationVariable FromClause ::= "FROM" IdentificationVariableDeclaration {"," IdentificationVariableDeclaration}* SubselectFromClause ::= "FROM" SubselectIdentificationVariableDeclaration {"," SubselectIdentificationVariableDeclaration}* WhereClause ::= "WHERE" ConditionalExpression HavingClause ::= "HAVING" ConditionalExpression GroupByClause ::= "GROUP" "BY" GroupByItem {"," GroupByItem}* OrderByClause ::= "ORDER" "BY" OrderByItem {"," OrderByItem}* Subselect ::= SimpleSelectClause SubselectFromClause [WhereClause] [GroupByClause] [HavingClause] [OrderByClause] UpdateItem ::= IdentificationVariable "." (StateField | SingleValuedAssociationField) "=" NewValue OrderByItem ::= (ResultVariable | SingleValuedPathExpression) ["ASC" | "DESC"] GroupByItem ::= IdentificationVariable | SingleValuedPathExpression NewValue ::= ScalarExpression | SimpleEntityExpression | "NULL" IdentificationVariableDeclaration ::= RangeVariableDeclaration [IndexBy] {JoinVariableDeclaration}* SubselectIdentificationVariableDeclaration ::= IdentificationVariableDeclaration | (AssociationPathExpression ["AS"] AliasIdentificationVariable) JoinVariableDeclaration ::= Join [IndexBy] RangeVariableDeclaration ::= AbstractSchemaName ["AS"] AliasIdentificationVariable Join ::= ["LEFT" ["OUTER"] | "INNER"] "JOIN" JoinAssociationPathExpression ["AS"] AliasIdentificationVariable ["WITH" ConditionalExpression] IndexBy ::= "INDEX" "BY" SimpleStateFieldPathExpression SelectExpression ::= IdentificationVariable | PartialObjectExpression | (AggregateExpression | "(" Subselect ")" | FunctionDeclaration | ScalarExpression) [["AS"] AliasResultVariable] SimpleSelectExpression ::= ScalarExpression | IdentificationVariable | (AggregateExpression [["AS"] AliasResultVariable]) PartialObjectExpression ::= "PARTIAL" IdentificationVariable "." PartialFieldSet PartialFieldSet ::= "{" SimpleStateField {"," SimpleStateField}* "}" ConditionalExpression ::= ConditionalTerm {"OR" ConditionalTerm}* ConditionalTerm ::= ConditionalFactor {"AND" ConditionalFactor}* ConditionalFactor ::= ["NOT"] ConditionalPrimary ConditionalPrimary ::= SimpleConditionalExpression | "(" ConditionalExpression ")" SimpleConditionalExpression ::= ComparisonExpression | BetweenExpression | LikeExpression | InExpression | NullComparisonExpression | ExistsExpression | EmptyCollectionComparisonExpression | CollectionMemberExpression | InstanceOfExpression EmptyCollectionComparisonExpression ::= CollectionValuedPathExpression "IS" ["NOT"] "EMPTY" CollectionMemberExpression ::= EntityExpression ["NOT"] "MEMBER" ["OF"] CollectionValuedPathExpression Literal ::= string | char | integer | float | boolean InParameter ::= Literal | InputParameter InputParameter ::= PositionalParameter | NamedParameter PositionalParameter ::= "?" integer NamedParameter ::= ":" string ArithmeticExpression ::= SimpleArithmeticExpression | "(" Subselect ")" SimpleArithmeticExpression ::= ArithmeticTerm {("+" | "-") ArithmeticTerm}* ArithmeticTerm ::= ArithmeticFactor {("*" | "/") ArithmeticFactor}* ArithmeticFactor ::= [("+" | "-")] ArithmeticPrimary ArithmeticPrimary ::= SingleValuedPathExpression | Literal | "(" SimpleArithmeticExpression ")" | FunctionsReturningNumerics | AggregateExpression | FunctionsReturningStrings | FunctionsReturningDatetime | IdentificationVariable | InputParameter | CaseExpression ScalarExpression ::= SimpleArithmeticExpression | StringPrimary | DateTimePrimary | StateFieldPathExpression | BooleanPrimary | EntityTypeExpression | CaseExpression StringExpression ::= StringPrimary | "(" Subselect ")" StringPrimary ::= StateFieldPathExpression | string | InputParameter | FunctionsReturningStrings | AggregateExpression | CaseExpression BooleanExpression ::= BooleanPrimary | "(" Subselect ")" BooleanPrimary ::= StateFieldPathExpression | boolean | InputParameter EntityExpression ::= SingleValuedAssociationPathExpression | SimpleEntityExpression SimpleEntityExpression ::= IdentificationVariable | InputParameter DatetimeExpression ::= DatetimePrimary | "(" Subselect ")" DatetimePrimary ::= StateFieldPathExpression | InputParameter | FunctionsReturningDatetime | AggregateExpression AggregateExpression ::= ("AVG" | "MAX" | "MIN" | "SUM") "(" ["DISTINCT"] StateFieldPathExpression ")" | "COUNT" "(" ["DISTINCT"] (IdentificationVariable | SingleValuedPathExpression) ")" CaseExpression ::= GeneralCaseExpression | SimpleCaseExpression | CoalesceExpression | NullifExpression GeneralCaseExpression ::= "CASE" WhenClause {WhenClause}* "ELSE" ScalarExpression "END" WhenClause ::= "WHEN" ConditionalExpression "THEN" ScalarExpression SimpleCaseExpression ::= "CASE" CaseOperand SimpleWhenClause {SimpleWhenClause}* "ELSE" ScalarExpression "END" CaseOperand ::= StateFieldPathExpression | TypeDiscriminator SimpleWhenClause ::= "WHEN" ScalarExpression "THEN" ScalarExpression CoalesceExpression ::= "COALESCE" "(" ScalarExpression {"," ScalarExpression}* ")" NullifExpression ::= "NULLIF" "(" ScalarExpression "," ScalarExpression ")" QuantifiedExpression ::= ("ALL" | "ANY" | "SOME") "(" Subselect ")" BetweenExpression ::= ArithmeticExpression ["NOT"] "BETWEEN" ArithmeticExpression "AND" ArithmeticExpression ComparisonExpression ::= ArithmeticExpression ComparisonOperator ( QuantifiedExpression | ArithmeticExpression ) InExpression ::= StateFieldPathExpression ["NOT"] "IN" "(" (InParameter {"," InParameter}* | Subselect) ")" InstanceOfExpression ::= IdentificationVariable ["NOT"] "INSTANCE" ["OF"] (InstanceOfParameter | "(" InstanceOfParameter {"," InstanceOfParameter}* ")") InstanceOfParameter ::= AbstractSchemaName | InputParameter LikeExpression ::= StringExpression ["NOT"] "LIKE" string ["ESCAPE" char] NullComparisonExpression ::= (SingleValuedPathExpression | InputParameter) "IS" ["NOT"] "NULL" ExistsExpression ::= ["NOT"] "EXISTS" "(" Subselect ")" ComparisonOperator ::= "=" | "<" | "<=" | "<>" | ">" | ">=" | "!=" FunctionDeclaration ::= FunctionsReturningStrings | FunctionsReturningNumerics | FunctionsReturningDateTime FunctionsReturningNumerics ::= "LENGTH" "(" StringPrimary ")" | "LOCATE" "(" StringPrimary "," StringPrimary ["," SimpleArithmeticExpression]")" | "ABS" "(" SimpleArithmeticExpression ")" | "SQRT" "(" SimpleArithmeticExpression ")" | "MOD" "(" SimpleArithmeticExpression "," SimpleArithmeticExpression ")" | "SIZE" "(" CollectionValuedPathExpression ")" FunctionsReturningDateTime ::= "CURRENT_DATE" | "CURRENT_TIME" | "CURRENT_TIMESTAMP" FunctionsReturningStrings ::= "CONCAT" "(" StringPrimary "," StringPrimary ")" | "SUBSTRING" "(" StringPrimary "," SimpleArithmeticExpression "," SimpleArithmeticExpression ")" | "TRIM" "(" [["LEADING" | "TRAILING" | "BOTH"] [char] "FROM"] StringPrimary ")" | "LOWER" "(" StringPrimary ")" | "UPPER" "(" StringPrimary ")"Thursday, March 1, 2012
  30. 30. Querying Since the letter size is 6, you may still not believe meThursday, March 1, 2012
  31. 31. Querying let’s try a real world example!Thursday, March 1, 2012
  32. 32. Querying Do you know Facebook activity wall?Thursday, March 1, 2012
  33. 33. Querying Do you know Facebook activity wall? Let’s show it!Thursday, March 1, 2012
  34. 34. SELECT e, a FROM Entry e JOIN e.wall w JOIN e.user u LEFT JOIN u.avatar av WHERE u = :user OR w IN ( SELECT uw FROM UserWall uw WHERE uw.user = :user OR uw.user IN ( SELECT CASE WHEN ua = us.subscriber THEN ub.id ELSE ua.id END FROM UserSubscription us JOIN us.friendship f JOIN f.userA ua JOIN f.userB ub WHERE us.muted = FALSE AND us.subscriber = :user AND f.status = Approved ) ) OR w IN ( SELECT gw FROM GroupWall gw WHERE gw.group IN ( SELECT DISTINCT g.id FROM GroupSubscription gs JOIN gs.group g WHERE gs.subscriber = :user AND gs.muted = FALSE AND gs.status = Approved ) ) ORDER BY e.created DESCThursday, March 1, 2012
  35. 35. SELECT e, a FROM Entry e JOIN e.wall w Entry you wrote JOIN e.user u LEFT JOIN u.avatar av WHERE u = :user OR w IN ( SELECT uw FROM UserWall uw WHERE uw.user = :user OR uw.user IN ( SELECT CASE WHEN ua = us.subscriber THEN ub.id ELSE ua.id END FROM UserSubscription us JOIN us.friendship f JOIN f.userA ua JOIN f.userB ub WHERE us.muted = FALSE AND us.subscriber = :user AND f.status = Approved ) ) OR w IN ( SELECT gw FROM GroupWall gw WHERE gw.group IN ( SELECT DISTINCT g.id FROM GroupSubscription gs JOIN gs.group g WHERE gs.subscriber = :user AND gs.muted = FALSE AND gs.status = Approved ) ) ORDER BY e.created DESCThursday, March 1, 2012
  36. 36. SELECT e, a FROM Entry e JOIN e.wall w Entry you wrote JOIN e.user u LEFT JOIN u.avatar av WHERE u = :user OR w IN ( Entry was in your Wall SELECT uw FROM UserWall uw WHERE uw.user = :user OR uw.user IN ( SELECT CASE WHEN ua = us.subscriber THEN ub.id ELSE ua.id END FROM UserSubscription us JOIN us.friendship f JOIN f.userA ua JOIN f.userB ub WHERE us.muted = FALSE AND us.subscriber = :user AND f.status = Approved ) ) OR w IN ( SELECT gw FROM GroupWall gw WHERE gw.group IN ( SELECT DISTINCT g.id FROM GroupSubscription gs JOIN gs.group g WHERE gs.subscriber = :user AND gs.muted = FALSE AND gs.status = Approved ) ) ORDER BY e.created DESCThursday, March 1, 2012
  37. 37. SELECT e, a FROM Entry e JOIN e.wall w Entry you wrote JOIN e.user u LEFT JOIN u.avatar av WHERE u = :user OR w IN ( Entry was in your Wall SELECT uw FROM UserWall uw WHERE uw.user = :user OR uw.user IN ( SELECT CASE WHEN ua = us.subscriber THEN ub.id ELSE ua.id END FROM UserSubscription us User is your friend, the friendship is JOIN us.friendship f approved and subscription is not muted JOIN f.userA ua JOIN f.userB ub WHERE us.muted = FALSE AND us.subscriber = :user AND f.status = Approved ) ) OR w IN ( SELECT gw FROM GroupWall gw WHERE gw.group IN ( SELECT DISTINCT g.id FROM GroupSubscription gs JOIN gs.group g WHERE gs.subscriber = :user AND gs.muted = FALSE AND gs.status = Approved ) ) ORDER BY e.created DESCThursday, March 1, 2012
  38. 38. SELECT e, a FROM Entry e JOIN e.wall w Entry you wrote JOIN e.user u LEFT JOIN u.avatar av WHERE u = :user OR w IN ( Entry was in your Wall SELECT uw FROM UserWall uw WHERE uw.user = :user OR uw.user IN ( SELECT CASE WHEN ua = us.subscriber THEN ub.id ELSE ua.id END FROM UserSubscription us User is your friend, the friendship is JOIN us.friendship f approved and subscription is not muted JOIN f.userA ua JOIN f.userB ub WHERE us.muted = FALSE AND us.subscriber = :user AND f.status = Approved ) ) OR w IN ( SELECT gw FROM GroupWall gw WHERE gw.group IN ( SELECT DISTINCT g.id FROM GroupSubscription gs JOIN gs.group g Group that you participate, is not WHERE gs.subscriber = :user AND gs.muted = FALSE muted and have an approved status AND gs.status = Approved ) ) ORDER BY e.created DESCThursday, March 1, 2012
  39. 39. Caching http://www.flickr.com/photos/eszter/3851576235/Thursday, March 1, 2012
  40. 40. Caching Doctrine supports 3 levels of caching...Thursday, March 1, 2012
  41. 41. Caching • Metadata cache • Query cache • Result cacheThursday, March 1, 2012
  42. 42. Caching Cache mapping of entities • Metadata cache • Query cache • Result cacheThursday, March 1, 2012
  43. 43. Caching Cache mapping of entities • Metadata cache • Query cache Cache DQL to SQL conversion • Result cacheThursday, March 1, 2012
  44. 44. Caching Cache mapping of entities • Metadata cache • Query cache Cache DQL to SQL conversion • Result cache Cache PDO result setThursday, March 1, 2012
  45. 45. Caching $query   = $entityManager->createQuery(     SELECT p        FROM Post p ); $query->useResultCache(true, 600, find-all-posts); $postList = $query->getResult();Thursday, March 1, 2012
  46. 46. Indexing http://www.flickr.com/photos/osuarchives/2659419894/Thursday, March 1, 2012
  47. 47. Indexing Doctrine is able to hint the Schema Tool to generate database indexes on specified table columnsThursday, March 1, 2012
  48. 48. Indexing /**  * @ORMEntity  * @ORMTable(  *     name = "users",  *     uniqueConstraints = {  *         @ORMUniqueConstraint(  *             name    = "user_unique",  *             columns = { "name" }  *         )  *     },  *     indexes = {  *         @ORMIndex(  *             name    = "login_idx",   *             columns = { "name", "password" }  *         )  *     }  * )  */ class User {     // ... }Thursday, March 1, 2012
  49. 49. Indexing @ORMUniqueConstraint(     name    = "user_unique",      columns = { "name" } ) CREATE UNIQUE INDEX user_unique ON TABLE users (name);Thursday, March 1, 2012
  50. 50. Indexing @ORMIndex(     name    = "login_idx",      columns = { "name", "password" } ) CREATE INDEX login_idx ON TABLE users (name, password);Thursday, March 1, 2012
  51. 51. Indexing @ORMIndex(     name    = "login_idx",      columns = { "name", "password" } ) Some drivers restrict to 32 chars as index name CREATE INDEX login_idx ON TABLE users (name, password);Thursday, March 1, 2012
  52. 52. Inheritance http://www.flickr.com/photos/duanekeys/307005468/Thursday, March 1, 2012
  53. 53. Inheritance Inheritance is a very deep topic in ORMsThursday, March 1, 2012
  54. 54. Inheritance Each inheritance type has advantages and disadvantagesThursday, March 1, 2012
  55. 55. Inheritance • Concrete Table Inheritance • Single Table Inheritance • Class Table InheritanceThursday, March 1, 2012
  56. 56. Inheritance One Class, one Table • Concrete Table Inheritance • Single Table Inheritance • Class Table InheritanceThursday, March 1, 2012
  57. 57. Inheritance One Class, one Table • Concrete Table Inheritance • Single Table Inheritance Multiple Classes, one Table • Class Table InheritanceThursday, March 1, 2012
  58. 58. Inheritance One Class, one Table • Concrete Table Inheritance • Single Table Inheritance Multiple Classes, one Table • Class Table Inheritance Multiple Classes, multiple TablesThursday, March 1, 2012
  59. 59. Inheritance • Concrete Table InheritanceThursday, March 1, 2012
  60. 60. Inheritance • Concrete Table Inheritance • ProsThursday, March 1, 2012
  61. 61. Inheritance • Concrete Table Inheritance • Pros • No locking problemsThursday, March 1, 2012
  62. 62. Inheritance • Concrete Table Inheritance • Pros • No locking problems • No irrelevant columnsThursday, March 1, 2012
  63. 63. Inheritance • Concrete Table Inheritance • Pros • No locking problems • No irrelevant columns • ConsThursday, March 1, 2012
  64. 64. Inheritance • Concrete Table Inheritance • Pros • No locking problems • No irrelevant columns • Cons • Difficult to deal with primary keysThursday, March 1, 2012
  65. 65. Inheritance • Concrete Table Inheritance • Pros • No locking problems • No irrelevant columns • Cons • Difficult to deal with primary keys • Search base class means search all tablesThursday, March 1, 2012
  66. 66. Inheritance • Concrete Table Inheritance • Pros • No locking problems • No irrelevant columns • Cons • Difficult to deal with primary keys • Search base class means search all tables • Update on columns means update on all hierarchy tablesThursday, March 1, 2012
  67. 67. Inheritance /**  * @ORMMappedSuperclass  */ class Person {     /**      * @ORMColumn(type="string", length=50)      */     protected $firstName;     /**      * @ORMColumn(type="string", length=50)      */     protected $lastName; } /**  * @ORMEntity  * @ORMTable(name="users")  */ class User extends Person {     /**      * @ORMId      * @ORMGeneratedValue      * @ORMColumn(type="integer")      */     protected $id; }Thursday, March 1, 2012
  68. 68. Inheritance CREATE TABLE users ( id INTEGER AUTO_INCREMENT NOT NULL, firstName VARCHAR(50) NOT NULL, lastName VARCHAR(50) NOT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB;Thursday, March 1, 2012
  69. 69. Inheritance • Single Table InheritanceThursday, March 1, 2012
  70. 70. Inheritance • Single Table Inheritance • ProsThursday, March 1, 2012
  71. 71. Inheritance • Single Table Inheritance • Pros • Only one table for hierarchyThursday, March 1, 2012
  72. 72. Inheritance • Single Table Inheritance • Pros • Only one table for hierarchy • No joinsThursday, March 1, 2012
  73. 73. Inheritance • Single Table Inheritance • Pros • Only one table for hierarchy • No joins • Refactoring of fields means no change to database tableThursday, March 1, 2012
  74. 74. Inheritance • Single Table Inheritance • Pros • Only one table for hierarchy • No joins • Refactoring of fields means no change to database table • ConsThursday, March 1, 2012
  75. 75. Inheritance • Single Table Inheritance • Pros • Only one table for hierarchy • No joins • Refactoring of fields means no change to database table • Cons • Waste of space in databaseThursday, March 1, 2012
  76. 76. Inheritance • Single Table Inheritance • Pros • Only one table for hierarchy • No joins • Refactoring of fields means no change to database table • Cons • Waste of space in database • Too many locks due to many accessesThursday, March 1, 2012
  77. 77. Inheritance • Single Table Inheritance • Pros • Only one table for hierarchy • No joins • Refactoring of fields means no change to database table • Cons • Waste of space in database • Too many locks due to many accesses • No duplicated field names with different meaningsThursday, March 1, 2012
  78. 78. Inheritance namespace MyAppEntity; /**  * @ORMEntity * @ORMTable(name= "people")  * @ORMInheritanceType("SINGLE_TABLE")  * @ORMDiscriminatorColumn(name="discr", type="string")  * @ORMDiscriminatorMap({  *     "user"     = "MyAppEntityUser",  *     "employee" = "MyAppEntityEmployee"  * })  */ class User {     // ... } /**  * @ORMEntity  */ class Employee extends User {      // ... }Thursday, March 1, 2012
  79. 79. Inheritance CREATE TABLE people ( id INT AUTO_INCREMENT NOT NULL, firstName VARCHAR(50) NOT NULL, lastName VARCHAR(50) NOT NULL, discr VARCHAR(20) NOT NULL, role VARCHAR(100) DEFAULT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB;Thursday, March 1, 2012
  80. 80. Inheritance • Class Table InheritanceThursday, March 1, 2012
  81. 81. Inheritance • Class Table Inheritance • ProsThursday, March 1, 2012
  82. 82. Inheritance • Class Table Inheritance • Pros • Easy to understandThursday, March 1, 2012
  83. 83. Inheritance • Class Table Inheritance • Pros • Easy to understand • Database space is optimized due to table normalizationThursday, March 1, 2012
  84. 84. Inheritance • Class Table Inheritance • Pros • Easy to understand • Database space is optimized due to table normalization • Direct relationship between Domain Model and DatabaseThursday, March 1, 2012
  85. 85. Inheritance • Class Table Inheritance • Pros • Easy to understand • Database space is optimized due to table normalization • Direct relationship between Domain Model and Database • ConsThursday, March 1, 2012
  86. 86. Inheritance • Class Table Inheritance • Pros • Easy to understand • Database space is optimized due to table normalization • Direct relationship between Domain Model and Database • Cons • Too many joinsThursday, March 1, 2012
  87. 87. Inheritance • Class Table Inheritance • Pros • Easy to understand • Database space is optimized due to table normalization • Direct relationship between Domain Model and Database • Cons • Too many joins • Refactoring of fields needs a database schema updateThursday, March 1, 2012
  88. 88. Inheritance • Class Table Inheritance • Pros • Easy to understand • Database space is optimized due to table normalization • Direct relationship between Domain Model and Database • Cons • Too many joins • Refactoring of fields needs a database schema update • Superclass table accessed a lot, it means it may enter in lock modeThursday, March 1, 2012
  89. 89. Inheritance namespace MyAppEntity; /**  * @ORMEntity * @ORMTable(name="users")  * @ORMInheritanceType("JOINED")  * @ORMDiscriminatorColumn( * name = "discr",  * type = "string", * length = 20 * )  * @ORMDiscriminatorMap({  *     "user"     = "MyAppEntityUser",  *     "employee" = "MyAppEntityEmployee"  * })  */ class User {     // ... } /**  * @ORMEntity  * @ORMTable(name= "employees")  */ class Employee extends User {      // ... }Thursday, March 1, 2012
  90. 90. Inheritance CREATE TABLE users ( id INT AUTO_INCREMENT NOT NULL, firstName VARCHAR(50) NOT NULL, lastName VARCHAR(50) NOT NULL, discr VARCHAR(20) NOT NULL, PRIMARY KEY (id) ) ENGINE = InnoDB; CREATE TABLE employees ( id INT NOT NULL, role VARCHAR(100) NOT NULL, PRIMARY KEY (id) ) ENGINE = InnoDB; ALTER TABLE employees ADD CONSTRAINT FK_BA82C300BF396750 FOREIGN KEY (id) REFERENCES users (id) ON DELETE CASCADE;Thursday, March 1, 2012
  91. 91. Inheritance What’s the problem with inheritance?Thursday, March 1, 2012
  92. 92. Inheritance What’s the problem with inheritance? HydrationThursday, March 1, 2012
  93. 93. InheritanceThursday, March 1, 2012
  94. 94. Inheritance • Inverse side *ToOneThursday, March 1, 2012
  95. 95. Inheritance • Inverse side *ToOne • Owning side *ToOne with InheritanceThursday, March 1, 2012
  96. 96. Inheritance • Inverse side *ToOne • Owning side *ToOne with Inheritance • Disabled deferEagerLoad while QueryingThursday, March 1, 2012
  97. 97. Cascades http://www.flickr.com/photos/over_kind_man/3158552109/Thursday, March 1, 2012
  98. 98. Cascades Ability to tell Unit Of Work of Doctrine how it should act when inspecting an association for graph changesThursday, March 1, 2012
  99. 99. Cascades Use judiciouslyThursday, March 1, 2012
  100. 100. Cascades It can heavily increase the graph edges to be navigated once the Compute Changeset algorithm is ranThursday, March 1, 2012
  101. 101. Cascades This means more time to persist, delete, merge, detach, refresh...Thursday, March 1, 2012
  102. 102. Cascades /**  * @ORMEntity  */ class User {     //...     /**      * Bidirectional - One-To-Many (INVERSE SIDE)      *      * @ORMOneToMany(      *     targetEntity = "Comment",       *     mappedBy     = "author",       *     cascade  = { "persist", "remove" }      * )      */     protected $commentsAuthored; }Thursday, March 1, 2012
  103. 103. Hydrators http://crimsonnightstock.deviantart.com/art/Yellow-Fire-Hydrant-Stock-100121929Thursday, March 1, 2012
  104. 104. Hydrators Doctrine comes with some useful result hydratorsThursday, March 1, 2012
  105. 105. Hydrators This means that not all times you need to retrieve objectsThursday, March 1, 2012
  106. 106. Hydrators • Object • Array • Scalar • Iterable • Simple Object • Single ScalarThursday, March 1, 2012
  107. 107. Hydrators • Object $resultList = $query->getResult(); • Array • Scalar • Iterable • Simple Object • Single ScalarThursday, March 1, 2012
  108. 108. Hydrators • Object $resultList = $query->getResult(); • Array $resultArray = $query->getArrayResult(); • Scalar • Iterable • Simple Object • Single ScalarThursday, March 1, 2012
  109. 109. Hydrators • Object $resultList = $query->getResult(); • Array $resultArray = $query->getArrayResult(); • Scalar $result = $query->getScalarResult(); • Iterable • Simple Object • Single ScalarThursday, March 1, 2012
  110. 110. Hydrators • Object $resultList = $query->getResult(); • Array $resultArray = $query->getArrayResult(); • Scalar $result = $query->getScalarResult(); • Iterable $iterator = $query->iterate(); • Simple Object • Single ScalarThursday, March 1, 2012
  111. 111. Hydrators • Object $resultList = $query->getResult(); • Array $resultArray = $query->getArrayResult(); • Scalar $result = $query->getScalarResult(); • Iterable $iterator = $query->iterate(); • Simple Object $result = $query->getSingleResult(); • Single ScalarThursday, March 1, 2012
  112. 112. Hydrators • Object $resultList = $query->getResult(); • Array $resultArray = $query->getArrayResult(); • Scalar $result = $query->getScalarResult(); • Iterable $iterator = $query->iterate(); • Simple Object $result = $query->getSingleResult(); • Single Scalar $result = $query->getSingleScalarResult();Thursday, March 1, 2012
  113. 113. http://joind.in/6053 Questions? @guilhermeblanco http://github.com/guilhermeblanco InstaClick Inc.Thursday, March 1, 2012
  114. 114. http://joind.in/6053 Questions? @guilhermeblanco http://github.com/guilhermeblanco InstaClick Inc. We are hiring! Talk to me privately if interestedThursday, March 1, 2012
  115. 115. http://joind.in/6053 Questions? Thank you! @guilhermeblanco http://github.com/guilhermeblanco InstaClick Inc. We are hiring! Talk to me privately if interestedThursday, March 1, 2012
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×