[ 
https://issues.apache.org/jira/browse/OPENJPA-2296?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13497953#comment-13497953
 ] 

Vermeulen commented on OPENJPA-2296:
------------------------------------

Perhaps the problem with bidirectional can be seen as a variation of the main 
Company - Project - Employee example. We have A *..1 B 1..* C, but C is equal 
to A.

Are there technical limitations why this cannot be efficiently fetched?
                
> N+1 select problems when eager fetching OneToOne and ManyToOne fields
> ---------------------------------------------------------------------
>
>                 Key: OPENJPA-2296
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-2296
>             Project: OpenJPA
>          Issue Type: Bug
>          Components: jdbc, kernel, performance
>    Affects Versions: 2.2.1
>            Reporter: Vermeulen
>            Priority: Critical
>         Attachments: OPENJPA-2296-tests.zip
>
>
> EDIT: 
>  - an N+1 select problem also always occurs when eagerly fetching a ManyToOne 
> field that is bidirectional (see TestManyOneEagerSQL)
>  - The patch of "RelationFieldStrategy.selectEagerJoin" I suggested works for 
> the unit tests but does not work in my real application so that may be a 
> different N+1 select issue. (Somehow my fields are in the list of eager 
> relations in OpenJPA's trace, but OpenJPA still uses a "load field" for them.)
> We have very serious performance problems in fetching our JPA entities caused 
> by N+1 select problems. I suspect that these are caused by a small bug in 
> OpenJPA's eager fetching implementation that should not be too hard to fix. 
> This is especially bad in our relatively complex reservation entity where we 
> need to eagerly fetch customer, contacts, orderlines, products etc. It takes 
> over 3 seconds to fetch a single reservation from a local db. The problem 
> seems to occur at multiple places in this object graph. The cause of the 
> problem is probably the following issue where eager fetching of relations of 
> toOne relations use neither a parallel or join select strategy but uses 
> separate "load field"s of EACH field of EACH toOne relation in the object 
> graph. I am not the only one having this issue, see also mailing list 
> http://openjpa.208410.n2.nabble.com/Fetchgroups-recursion-problem-td3874382.html#a7581598
> Suppose we have entities Company 1..* Employee 1..* Project
> According to Chapter 8. Eager Fetching of the manual: "Continuing our 
> example, if the Employee class had a list of Projects in one of the fetch 
> groups being loaded, OpenJPA would execute a single additional select in 
> parallel to load the projects of all employees of the matching companies."
> This is indeed what happens when both relations are eager (or are marked lazy 
> but are in the fetchplan). The number of queries needed to fetch a Company 
> does not depend on the number of employees or projects:
> 8913  testPU  TRACE  [main] openjpa.Query - Executing query: SELECT z FROM 
> Company z
> 19885  testPU  TRACE  [main] openjpa.jdbc.SQLDiag - Eager relations: 
> [entities.Employee.projects, entities.Company.employees]
> 19889  testPU  TRACE  [main] openjpa.jdbc.SQL - <t 12833564, conn 5535786> 
> executing prepstmnt 20965449 SELECT t0.id, t0.name FROM Company t0
> 19891  testPU  TRACE  [main] openjpa.jdbc.SQL - <t 12833564, conn 5535786> [2 
> ms] spent
> 20237  testPU  TRACE  [main] openjpa.jdbc.SQLDiag - Eager relations: 
> [entities.Employee.projects, entities.Company.employees]
> 20237  testPU  TRACE  [main] openjpa.jdbc.SQL - <t 12833564, conn 5535786> 
> executing prepstmnt 21924553 SELECT t0.id, t1.id, t1.name FROM Company t0 
> INNER JOIN Employee t1 ON t0.id = t1.COMPANY_ID ORDER BY t0.id ASC
> 20248  testPU  TRACE  [main] openjpa.jdbc.SQL - <t 12833564, conn 5535786> 
> [10 ms] spent
> 21308  testPU  TRACE  [main] openjpa.jdbc.SQLDiag - Eager relations: 
> [entities.Employee.projects, entities.Company.employees]
> 21309  testPU  TRACE  [main] openjpa.jdbc.SQL - <t 12833564, conn 5535786> 
> executing prepstmnt 13123665 SELECT DISTINCT t1.id, t2.id, t2.name FROM 
> Company t0 INNER JOIN Employee t1 ON t0.id = t1.COMPANY_ID INNER JOIN Project 
> t2 ON t1.id = t2.EMPLOYEE_ID ORDER BY t1.id ASC
> 21376  testPU  TRACE  [main] openjpa.jdbc.SQL - <t 12833564, conn 5535786> 
> [67 ms] spent
> 22247  testPU  TRACE  [main] openjpa.jdbc.JDBC - <t 12833564, conn 0> [0 ms] 
> close
> However when the relation between Company and Employee is replaced with a 
> OneToOne or ManyToOne relation, this efficient eager fetching fails and 
> OpenJPA resorts to single object loads for the projects field of each 
> Employee:
> .... 
> 41580  testPU  TRACE  [main] openjpa.Query - Executing query: SELECT z FROM 
> Company z
> 49121  testPU  TRACE  [main] openjpa.jdbc.SQLDiag - Eager relations: 
> [entities.Company.employee]
> 49121  testPU  TRACE  [main] openjpa.jdbc.SQL - <t 22418487, conn 10229202> 
> executing prepstmnt 17563180 SELECT t0.id, t1.id, t1.name, t0.name FROM 
> Company t0 LEFT OUTER JOIN Employee t1 ON t0.id = t1.COMPANY_ID
> 49142  testPU  TRACE  [main] openjpa.jdbc.SQL - <t 22418487, conn 10229202> 
> [21 ms] spent
> 61282  testPU  TRACE  [main] openjpa.jdbc.SQLDiag - load field: 'projects' 
> for oid=51 class entities.Employee
> 62593  testPU  TRACE  [main] openjpa.jdbc.SQL - <t 22418487, conn 10229202> 
> executing prepstmnt 27638389 SELECT t0.id, t0.name FROM Project t0 WHERE 
> t0.EMPLOYEE_ID = ? [params=?]
> 62594  testPU  TRACE  [main] openjpa.jdbc.SQL - <t 22418487, conn 10229202> 
> [1 ms] spent
> 64554  testPU  TRACE  [main] openjpa.jdbc.SQLDiag - load field: 'projects' 
> for oid=52 class entities.Employee
> 67645  testPU  TRACE  [main] openjpa.jdbc.SQL - <t 22418487, conn 10229202> 
> executing prepstmnt 18914646 SELECT t0.id, t0.name FROM Project t0 WHERE 
> t0.EMPLOYEE_ID = ? [params=?]
> .... 
> In the first (efficient) case OpenJPA logs
>   openjpa.jdbc.SQLDiag - Eager relations: [entities.Employee.projects, 
> entities.Company.employees]
>  
> In the second (inefficient) case OpenJPA logs
>   openjpa.jdbc.SQLDiag - Eager relations: [entities.Company.employee]
> This issue may be related to 
> https://issues.apache.org/jira/browse/OPENJPA-1920 which also uses single 
> "load field"s.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

Reply via email to