Your SlideShare is downloading. ×
0
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
ORM dont kill your DB, developers do
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

ORM dont kill your DB, developers do

7,902

Published on

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

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
0 Comments
27 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
7,902
On Slideshare
0
From Embeds
0
Number of Embeds
7
Actions
Shares
0
Downloads
185
Comments
0
Likes
27
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. ORM Database Developers http://www.flickr.com/photos/hoyvinmayvin/5103806609/ Guilherme BlancoThursday, March 1, 2012
  • 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. Agenda http://www.flickr.com/photos/emerzh/3072428824/Thursday, March 1, 2012
  • 4. General Rule RTFMThursday, March 1, 2012
  • 5. Dependency management http://www.flickr.com/photos/ollesvensson/3694625903/Thursday, March 1, 2012
  • 6. Dependency ManagementThursday, March 1, 2012
  • 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. Dependency ManagementThursday, March 1, 2012
  • 9. Dependency ManagementThursday, March 1, 2012
  • 10. Dependency Management namespace AppBundleBlogBundleEntity; /**  * @ORMEntity  */ class Post {     // ... } namespace AppBundleCommentBundleEntity; /**  * @ORMEntity  */ class Comment {     /**      * @ORMManyToOne(targetEntity="AppBlog:Post")      */     protected $post; }Thursday, March 1, 2012
  • 11. Fetch Mode http://www.flickr.com/photos/comedynose/5318259802/Thursday, March 1, 2012
  • 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. Fetch Mode Supported by all association types...Thursday, March 1, 2012
  • 14. Fetch Mode • OneToOne • OneToMany • ManyToOne • ManyToManyThursday, March 1, 2012
  • 15. Fetch Mode Available fetch modes...Thursday, March 1, 2012
  • 16. Fetch Mode • EAGER • LAZY (default) • EXTRA_LAZYThursday, March 1, 2012
  • 17. Fetch Mode An association (collection or attribute), is fetched immediately when owner is loaded • EAGER • LAZY (default) • EXTRA_LAZYThursday, March 1, 2012
  • 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. 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. 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. 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. Querying http://www.flickr.com/photos/pschadler/4932737690/Thursday, March 1, 2012
  • 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. 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. 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. 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. Querying I know you all don’t trust me...Thursday, March 1, 2012
  • 28. Querying ...but take a look at its EBNF grammar...Thursday, March 1, 2012
  • 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. Querying Since the letter size is 6, you may still not believe meThursday, March 1, 2012
  • 31. Querying let’s try a real world example!Thursday, March 1, 2012
  • 32. Querying Do you know Facebook activity wall?Thursday, March 1, 2012
  • 33. Querying Do you know Facebook activity wall? Let’s show it!Thursday, March 1, 2012
  • 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. 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. 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. 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. 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. Caching http://www.flickr.com/photos/eszter/3851576235/Thursday, March 1, 2012
  • 40. Caching Doctrine supports 3 levels of caching...Thursday, March 1, 2012
  • 41. Caching • Metadata cache • Query cache • Result cacheThursday, March 1, 2012
  • 42. Caching Cache mapping of entities • Metadata cache • Query cache • Result cacheThursday, March 1, 2012
  • 43. Caching Cache mapping of entities • Metadata cache • Query cache Cache DQL to SQL conversion • Result cacheThursday, March 1, 2012
  • 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. Caching $query   = $entityManager->createQuery(     SELECT p        FROM Post p ); $query->useResultCache(true, 600, find-all-posts); $postList = $query->getResult();Thursday, March 1, 2012
  • 46. Indexing http://www.flickr.com/photos/osuarchives/2659419894/Thursday, March 1, 2012
  • 47. Indexing Doctrine is able to hint the Schema Tool to generate database indexes on specified table columnsThursday, March 1, 2012
  • 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. Indexing @ORMUniqueConstraint(     name    = "user_unique",      columns = { "name" } ) CREATE UNIQUE INDEX user_unique ON TABLE users (name);Thursday, March 1, 2012
  • 50. Indexing @ORMIndex(     name    = "login_idx",      columns = { "name", "password" } ) CREATE INDEX login_idx ON TABLE users (name, password);Thursday, March 1, 2012
  • 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. Inheritance http://www.flickr.com/photos/duanekeys/307005468/Thursday, March 1, 2012
  • 53. Inheritance Inheritance is a very deep topic in ORMsThursday, March 1, 2012
  • 54. Inheritance Each inheritance type has advantages and disadvantagesThursday, March 1, 2012
  • 55. Inheritance • Concrete Table Inheritance • Single Table Inheritance • Class Table InheritanceThursday, March 1, 2012
  • 56. Inheritance One Class, one Table • Concrete Table Inheritance • Single Table Inheritance • Class Table InheritanceThursday, March 1, 2012
  • 57. Inheritance One Class, one Table • Concrete Table Inheritance • Single Table Inheritance Multiple Classes, one Table • Class Table InheritanceThursday, March 1, 2012
  • 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. Inheritance • Concrete Table InheritanceThursday, March 1, 2012
  • 60. Inheritance • Concrete Table Inheritance • ProsThursday, March 1, 2012
  • 61. Inheritance • Concrete Table Inheritance • Pros • No locking problemsThursday, March 1, 2012
  • 62. Inheritance • Concrete Table Inheritance • Pros • No locking problems • No irrelevant columnsThursday, March 1, 2012
  • 63. Inheritance • Concrete Table Inheritance • Pros • No locking problems • No irrelevant columns • ConsThursday, March 1, 2012
  • 64. Inheritance • Concrete Table Inheritance • Pros • No locking problems • No irrelevant columns • Cons • Difficult to deal with primary keysThursday, March 1, 2012
  • 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. 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. 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. 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. Inheritance • Single Table InheritanceThursday, March 1, 2012
  • 70. Inheritance • Single Table Inheritance • ProsThursday, March 1, 2012
  • 71. Inheritance • Single Table Inheritance • Pros • Only one table for hierarchyThursday, March 1, 2012
  • 72. Inheritance • Single Table Inheritance • Pros • Only one table for hierarchy • No joinsThursday, March 1, 2012
  • 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. 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. 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. 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. 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. 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. 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. Inheritance • Class Table InheritanceThursday, March 1, 2012
  • 81. Inheritance • Class Table Inheritance • ProsThursday, March 1, 2012
  • 82. Inheritance • Class Table Inheritance • Pros • Easy to understandThursday, March 1, 2012
  • 83. Inheritance • Class Table Inheritance • Pros • Easy to understand • Database space is optimized due to table normalizationThursday, March 1, 2012
  • 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. 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. 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. 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. 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. 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. 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. Inheritance What’s the problem with inheritance?Thursday, March 1, 2012
  • 92. Inheritance What’s the problem with inheritance? HydrationThursday, March 1, 2012
  • 93. InheritanceThursday, March 1, 2012
  • 94. Inheritance • Inverse side *ToOneThursday, March 1, 2012
  • 95. Inheritance • Inverse side *ToOne • Owning side *ToOne with InheritanceThursday, March 1, 2012
  • 96. Inheritance • Inverse side *ToOne • Owning side *ToOne with Inheritance • Disabled deferEagerLoad while QueryingThursday, March 1, 2012
  • 97. Cascades http://www.flickr.com/photos/over_kind_man/3158552109/Thursday, March 1, 2012
  • 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. Cascades Use judiciouslyThursday, March 1, 2012
  • 100. Cascades It can heavily increase the graph edges to be navigated once the Compute Changeset algorithm is ranThursday, March 1, 2012
  • 101. Cascades This means more time to persist, delete, merge, detach, refresh...Thursday, March 1, 2012
  • 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. Hydrators http://crimsonnightstock.deviantart.com/art/Yellow-Fire-Hydrant-Stock-100121929Thursday, March 1, 2012
  • 104. Hydrators Doctrine comes with some useful result hydratorsThursday, March 1, 2012
  • 105. Hydrators This means that not all times you need to retrieve objectsThursday, March 1, 2012
  • 106. Hydrators • Object • Array • Scalar • Iterable • Simple Object • Single ScalarThursday, March 1, 2012
  • 107. Hydrators • Object $resultList = $query->getResult(); • Array • Scalar • Iterable • Simple Object • Single ScalarThursday, March 1, 2012
  • 108. Hydrators • Object $resultList = $query->getResult(); • Array $resultArray = $query->getArrayResult(); • Scalar • Iterable • Simple Object • Single ScalarThursday, March 1, 2012
  • 109. Hydrators • Object $resultList = $query->getResult(); • Array $resultArray = $query->getArrayResult(); • Scalar $result = $query->getScalarResult(); • Iterable • Simple Object • Single ScalarThursday, March 1, 2012
  • 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. 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. 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. http://joind.in/6053 Questions? @guilhermeblanco http://github.com/guilhermeblanco InstaClick Inc.Thursday, March 1, 2012
  • 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. 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

×