SlideShare a Scribd company logo
ORM and..
Bad habits
Patryk Szlagowski
Patryk Szlagowski
Backend Developer at Logisfera Nova - lsn.io
@abdulklarapl
Captain at FunkyMonkeyLabs
1. ORM - what is it?

2. Problem 1 - greedy fetching

3. Problem 2 - „lets map everything”

4. Performance table

5. Conclusions

6. Conclusions - moar
1. ORM
In one picture
ORMDB applicationDBAL*
/**

* @Route("/", name="homepage")

*/

public function indexAction(Request $request)

{

return $this->render('default/index.html.twig', array(

'news' => $this->getDoctrine()
->getRepository('AppBundle:Post')
->findAll()

));

}
2. Problem 1 - greedy fetching
/**

* @return Post[]

*/

public function getAll()

{

$qb = $this->createQueryBuilder("post");

$qb

->select("post, author, role,
category, comments,
commentsAuthor,
commentsAuthorRole")

->join("post.category", "category")

->join("post.author", "author")

->join("author.role", "role")

->join("post.comments", "comments")

->join("comments.author", "commentsAuthor")

->join("commentsAuthor.role", "commentsAuthorRole");



return $qb->getQuery()->getResult();

}
That is nice. But wait.. How is possible, that results can be
mapped to relations from this?
Let’s add custom method in repository and control the joins
2. Problem 1 - greedy fetching
2. Problem 1 - greedy fetching
SELECT {fields}

FROM post p0_

INNER JOIN dictionary_item d1_ ON p0_.category_id = d1_.id

INNER JOIN person p2_ ON p0_.author_id = p2_.id

INNER JOIN dictionary_item d3_ ON p2_.role_id = d3_.id

INNER JOIN COMMENT c4_ ON p0_.id = c4_.post_id

INNER JOIN person p5_ ON c4_.author_id = p5_.id

INNER JOIN dictionary_item d6_ ON p5_.role_id = d6_.id
That is I expected. 3 rows for 1 post (3 comments). ORM mapped columns to many objects,
grouped by primary key.

But let’s imagine, what if we have 100 records (A) with relation to B (10 records each) AND B-C
(with another 10 records for each B)? 10000 records to map.
2. Problem 1 - greedy fetching
What’s going on?
What if..
I tell you, that you can get all of the rows by one query, without multiply results rows number?
IMPOSSIBRU
Cons
• PostgreSQL
• JSON functions
• complicated query
• slower than simple

query
Pros
• JSON response
• whole object in one row
• what you see in results, 

it’s what you get in app
SELECT array_to_json(

array_agg(

row_to_json({alias})

)

)

FROM (

{subquery}

) AS {alias}
SELECT array_to_json(array_agg(row_to_json(results)))

FROM (

SELECT

post.id, post.create_date, post.content, post.title,

(SELECT row_to_json(author)

FROM (

SELECT

person.*,

(

SELECT row_to_json(role)

FROM (

SELECT * FROM dictionary_item di WHERE di.id = person.role_id

) AS role

) AS role

FROM person WHERE person.id = post.author_id

) as author) AS author,

(

SELECT row_to_json(category)

FROM dictionary_item category WHERE category.id = post.category_id

) as category,

(

SELECT array_to_json(array_agg(row_to_json(comments)))

FROM (

SELECT comment.title, comment.content, (

SELECT row_to_json(comment_author)

FROM (

SELECT person.*, (

SELECT row_to_json(role)

FROM (

SELECT *

FROM dictionary_item di

WHERE di.id = person.role_id

) AS role

) AS role

FROM person

WHERE person.id = comment.author_id

) AS comment_author

) AS author

FROM comment where comment.post_id = post.id

) AS comments

) as comments

FROM post

) AS results
3. Problem 2 - results mapping
ORMDataSource
response
application
model
REST
response
In most cases
for what?
3. Problem 2 - results mapping
DataSource
response
array/hashmap response REST
response
In most cases
Built-in findAll
function
Simple query with
joins, mapped to
objects
array_to_json query,
mapped to objects
array_to_json query,
no mapping, return
in REST Api
query time 2326ms 52ms 101ms 111ms
memory usage 82MB 51MB 33.5MB 17.2MB
total (with render)
time
7464ms 2100ms 1755ms 364ms
number of queries 4405 1 1 1
4. All about performance
* tested with 400 posts, 10 comments per post, one author per comment, author per post, label per category
5. Conclusions
Query builders
Query builders
$this->repository->findAll()
4405
trolololo
vs
$this->repository->customFindAll()
1
1. Maybe we should start using aggregating functions to get data from DB

2. If you don’t have to to transform DB response to object - don’t do it

3. Don’t use built-in functions such as findBy, findAll, findOne, sth, sth

4. Write your own functions with joins, groups to take control over the query

5. Remember about lazy loading
6. Conclusions
Thank youI want to talk with you

More Related Content

PDF
PageObject
PDF
Developing Applications with MySQL and Java for beginners
PDF
Class-based views with Django
PDF
JavaScript Abstraction
KEY
JavaScript Growing Up
PPTX
PDF
Beyond the DOM: Sane Structure for JS Apps
PPTX
Powerful Generic Patterns With Django
PageObject
Developing Applications with MySQL and Java for beginners
Class-based views with Django
JavaScript Abstraction
JavaScript Growing Up
Beyond the DOM: Sane Structure for JS Apps
Powerful Generic Patterns With Django

What's hot (20)

KEY
What's new in Django 1.2?
DOC
Create a Customized GMF DnD Framework
PDF
Javascript Design Patterns
PDF
Js objects
PDF
ERRest: the Basics
PDF
Swift, functional programming, and the future of Objective-C
PDF
Funcitonal Swift Conference: The Functional Way
PDF
The Django Book, Chapter 16: django.contrib
PPTX
Fact, Fiction, and FP
KEY
Django Pro ORM
PDF
PPTX
ActionScript3 collection query API proposal
PDF
Django design-patterns
PDF
ERRest - The Next Steps
PDF
Dollar symbol
KEY
2012 oct-12 - java script inheritance
PDF
ERRest in Depth
KEY
Advanced Django ORM techniques
PDF
Declarative Data Modeling in Python
PDF
ESNext for humans - LvivJS 16 August 2014
What's new in Django 1.2?
Create a Customized GMF DnD Framework
Javascript Design Patterns
Js objects
ERRest: the Basics
Swift, functional programming, and the future of Objective-C
Funcitonal Swift Conference: The Functional Way
The Django Book, Chapter 16: django.contrib
Fact, Fiction, and FP
Django Pro ORM
ActionScript3 collection query API proposal
Django design-patterns
ERRest - The Next Steps
Dollar symbol
2012 oct-12 - java script inheritance
ERRest in Depth
Advanced Django ORM techniques
Declarative Data Modeling in Python
ESNext for humans - LvivJS 16 August 2014
Ad

Similar to ORM - tuningujemy podejście do mapowania (20)

PDF
Functional programming using underscorejs
PDF
Migrare da symfony 1 a Symfony2
PDF
Mongoskin - Guilin
PDF
1. Design a Java interface called Priority that includes two methods.pdf
PDF
Spring boot
PDF
Revisiting SOLID Principles
PPTX
2017 02-07 - elastic & spark. building a search geo locator
PPTX
2017 02-07 - elastic & spark. building a search geo locator
PPT
Micro-ORM Introduction - Don't overcomplicate
PDF
PLEASE MAKE SURE THE PROGRAM IS ASKING FOR INPUT FROM USER TO ADD OR.pdf
PPTX
Groovy vs Boilerplate and Ceremony Code
PPTX
Thinking Functionally with JavaScript
PDF
Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...
PPTX
Golang slidesaudrey
PDF
Selectors and normalizing state shape
PDF
HELP IN JAVACreate a main method and use these input files to tes.pdf
PDF
Et si on en finissait avec CRUD ?
PDF
Clean Javascript
PDF
Es6 modules-and-bundlers
PDF
droidparts
Functional programming using underscorejs
Migrare da symfony 1 a Symfony2
Mongoskin - Guilin
1. Design a Java interface called Priority that includes two methods.pdf
Spring boot
Revisiting SOLID Principles
2017 02-07 - elastic & spark. building a search geo locator
2017 02-07 - elastic & spark. building a search geo locator
Micro-ORM Introduction - Don't overcomplicate
PLEASE MAKE SURE THE PROGRAM IS ASKING FOR INPUT FROM USER TO ADD OR.pdf
Groovy vs Boilerplate and Ceremony Code
Thinking Functionally with JavaScript
Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...
Golang slidesaudrey
Selectors and normalizing state shape
HELP IN JAVACreate a main method and use these input files to tes.pdf
Et si on en finissait avec CRUD ?
Clean Javascript
Es6 modules-and-bundlers
droidparts
Ad

More from 3camp (20)

PDF
Ochrona podatnych webaplikacji za pomocą wirtualnych poprawek
PDF
HTTPS bez wymówek
PPTX
Jak udokumentować bazę danych
PDF
No pressure, no diamonds. Rzecz o łamaniu zasad w projektach.
PDF
W poszukiwaniu procesu doskonałego. Wdrożenie Scruma, Continuous Integrations...
PDF
Wykorzystanie języka Kotlin do aplikacji na platformie Android
PDF
Learn you some rx for the greater good
PDF
Google App Engine i Google Play Services w Twoich aplikacjach
PDF
Reakcja łańcuchowa, czyli React.js w praktyce
PDF
Odtwarzanie multimediów w HTML5, czyli Player przez duże „P”
PPTX
AngularJS (nie) nadaje się do dużego projektu
PDF
Przemysław Bartkowiak - Sam ustalasz ile za to zapłacisz – czyli nowy wymiar ...
PDF
Mirek Wąsowicz - Segment jednego, dokąd zmierza marketing online?
PDF
Artur Senk, OKE Poland, Big Data na zakupach
PDF
Piotr Macuk, Konfeo.com, Programista i biznes – plusy i minusy własnej działa...
PPTX
Marcin Maj, Kainos - QA – wartko, zmiennie i interdyscyplinarnie
PDF
Jak przesiąść się na rower na dwóch kółkach? Od trzyosobowego startupu do spó...
PDF
Łukasz Brzeziński - Jak zarabiać z Wikingami? Czyli monetyzacja portalu inter...
PDF
Marcin Szeląg, InnovationNest, Startup Risk Model
PDF
JSON, REST API
Ochrona podatnych webaplikacji za pomocą wirtualnych poprawek
HTTPS bez wymówek
Jak udokumentować bazę danych
No pressure, no diamonds. Rzecz o łamaniu zasad w projektach.
W poszukiwaniu procesu doskonałego. Wdrożenie Scruma, Continuous Integrations...
Wykorzystanie języka Kotlin do aplikacji na platformie Android
Learn you some rx for the greater good
Google App Engine i Google Play Services w Twoich aplikacjach
Reakcja łańcuchowa, czyli React.js w praktyce
Odtwarzanie multimediów w HTML5, czyli Player przez duże „P”
AngularJS (nie) nadaje się do dużego projektu
Przemysław Bartkowiak - Sam ustalasz ile za to zapłacisz – czyli nowy wymiar ...
Mirek Wąsowicz - Segment jednego, dokąd zmierza marketing online?
Artur Senk, OKE Poland, Big Data na zakupach
Piotr Macuk, Konfeo.com, Programista i biznes – plusy i minusy własnej działa...
Marcin Maj, Kainos - QA – wartko, zmiennie i interdyscyplinarnie
Jak przesiąść się na rower na dwóch kółkach? Od trzyosobowego startupu do spó...
Łukasz Brzeziński - Jak zarabiać z Wikingami? Czyli monetyzacja portalu inter...
Marcin Szeląg, InnovationNest, Startup Risk Model
JSON, REST API

Recently uploaded (20)

PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PDF
Unlocking AI with Model Context Protocol (MCP)
PDF
Network Security Unit 5.pdf for BCA BBA.
DOCX
The AUB Centre for AI in Media Proposal.docx
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
cuic standard and advanced reporting.pdf
PPTX
A Presentation on Artificial Intelligence
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PDF
Encapsulation_ Review paper, used for researhc scholars
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
KodekX | Application Modernization Development
PPTX
MYSQL Presentation for SQL database connectivity
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Agricultural_Statistics_at_a_Glance_2022_0.pdf
Unlocking AI with Model Context Protocol (MCP)
Network Security Unit 5.pdf for BCA BBA.
The AUB Centre for AI in Media Proposal.docx
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
Diabetes mellitus diagnosis method based random forest with bat algorithm
cuic standard and advanced reporting.pdf
A Presentation on Artificial Intelligence
Chapter 3 Spatial Domain Image Processing.pdf
Per capita expenditure prediction using model stacking based on satellite ima...
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
Digital-Transformation-Roadmap-for-Companies.pptx
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Dropbox Q2 2025 Financial Results & Investor Presentation
Encapsulation_ Review paper, used for researhc scholars
Advanced methodologies resolving dimensionality complications for autism neur...
KodekX | Application Modernization Development
MYSQL Presentation for SQL database connectivity
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...

ORM - tuningujemy podejście do mapowania

  • 2. Patryk Szlagowski Backend Developer at Logisfera Nova - lsn.io @abdulklarapl Captain at FunkyMonkeyLabs
  • 3. 1. ORM - what is it? 2. Problem 1 - greedy fetching 3. Problem 2 - „lets map everything” 4. Performance table 5. Conclusions 6. Conclusions - moar
  • 4. 1. ORM In one picture ORMDB applicationDBAL*
  • 5. /**
 * @Route("/", name="homepage")
 */
 public function indexAction(Request $request)
 {
 return $this->render('default/index.html.twig', array(
 'news' => $this->getDoctrine() ->getRepository('AppBundle:Post') ->findAll()
 ));
 } 2. Problem 1 - greedy fetching
  • 6. /**
 * @return Post[]
 */
 public function getAll()
 {
 $qb = $this->createQueryBuilder("post");
 $qb
 ->select("post, author, role, category, comments, commentsAuthor, commentsAuthorRole")
 ->join("post.category", "category")
 ->join("post.author", "author")
 ->join("author.role", "role")
 ->join("post.comments", "comments")
 ->join("comments.author", "commentsAuthor")
 ->join("commentsAuthor.role", "commentsAuthorRole");
 
 return $qb->getQuery()->getResult();
 } That is nice. But wait.. How is possible, that results can be mapped to relations from this? Let’s add custom method in repository and control the joins 2. Problem 1 - greedy fetching
  • 7. 2. Problem 1 - greedy fetching
  • 8. SELECT {fields}
 FROM post p0_
 INNER JOIN dictionary_item d1_ ON p0_.category_id = d1_.id
 INNER JOIN person p2_ ON p0_.author_id = p2_.id
 INNER JOIN dictionary_item d3_ ON p2_.role_id = d3_.id
 INNER JOIN COMMENT c4_ ON p0_.id = c4_.post_id
 INNER JOIN person p5_ ON c4_.author_id = p5_.id
 INNER JOIN dictionary_item d6_ ON p5_.role_id = d6_.id That is I expected. 3 rows for 1 post (3 comments). ORM mapped columns to many objects, grouped by primary key. But let’s imagine, what if we have 100 records (A) with relation to B (10 records each) AND B-C (with another 10 records for each B)? 10000 records to map. 2. Problem 1 - greedy fetching What’s going on?
  • 9. What if.. I tell you, that you can get all of the rows by one query, without multiply results rows number? IMPOSSIBRU
  • 10. Cons • PostgreSQL • JSON functions • complicated query • slower than simple
 query Pros • JSON response • whole object in one row • what you see in results, 
 it’s what you get in app SELECT array_to_json(
 array_agg(
 row_to_json({alias})
 )
 )
 FROM (
 {subquery}
 ) AS {alias} SELECT array_to_json(array_agg(row_to_json(results)))
 FROM (
 SELECT
 post.id, post.create_date, post.content, post.title,
 (SELECT row_to_json(author)
 FROM (
 SELECT
 person.*,
 (
 SELECT row_to_json(role)
 FROM (
 SELECT * FROM dictionary_item di WHERE di.id = person.role_id
 ) AS role
 ) AS role
 FROM person WHERE person.id = post.author_id
 ) as author) AS author,
 (
 SELECT row_to_json(category)
 FROM dictionary_item category WHERE category.id = post.category_id
 ) as category,
 (
 SELECT array_to_json(array_agg(row_to_json(comments)))
 FROM (
 SELECT comment.title, comment.content, (
 SELECT row_to_json(comment_author)
 FROM (
 SELECT person.*, (
 SELECT row_to_json(role)
 FROM (
 SELECT *
 FROM dictionary_item di
 WHERE di.id = person.role_id
 ) AS role
 ) AS role
 FROM person
 WHERE person.id = comment.author_id
 ) AS comment_author
 ) AS author
 FROM comment where comment.post_id = post.id
 ) AS comments
 ) as comments
 FROM post
 ) AS results
  • 11. 3. Problem 2 - results mapping ORMDataSource response application model REST response In most cases for what?
  • 12. 3. Problem 2 - results mapping DataSource response array/hashmap response REST response In most cases
  • 13. Built-in findAll function Simple query with joins, mapped to objects array_to_json query, mapped to objects array_to_json query, no mapping, return in REST Api query time 2326ms 52ms 101ms 111ms memory usage 82MB 51MB 33.5MB 17.2MB total (with render) time 7464ms 2100ms 1755ms 364ms number of queries 4405 1 1 1 4. All about performance * tested with 400 posts, 10 comments per post, one author per comment, author per post, label per category
  • 14. 5. Conclusions Query builders Query builders $this->repository->findAll() 4405 trolololo vs $this->repository->customFindAll() 1
  • 15. 1. Maybe we should start using aggregating functions to get data from DB 2. If you don’t have to to transform DB response to object - don’t do it 3. Don’t use built-in functions such as findBy, findAll, findOne, sth, sth 4. Write your own functions with joins, groups to take control over the query 5. Remember about lazy loading 6. Conclusions
  • 16. Thank youI want to talk with you