Issue Details (XML | Word | Printable)

Key: NUCRDBMS-223
Type: Bug Bug
Status: Closed Closed
Resolution: Fixed
Priority: Major Major
Assignee: Andy Jefferson
Reporter: Clive Cox
Votes: 0
Watchers: 2
Operations

If you were logged in you would be able to see more operations.
DataNucleus Store RDBMS

JDOQL : SQL for Set contains() when using join table not optimal

Created: 24/Apr/06 02:34 PM   Updated: 11/Sep/09 08:41 AM   Resolved: 20/Jul/09 11:41 AM
Component/s: Queries
Affects Version/s: None
Fix Version/s: 2.0.0.m1

File Attachments: 1. Zip Archive Main.zip (2 kB)


Datastore: MySQL


 Description  « Hide
The SQL created for Querying a Set with contains for a FCO is incorrect. It does produce the correct result but there are severe performance issues. An example test will be attached.
But the simple test case discussed in the forums is repeated below, along with required change suggested by Erik,

Example:
2 classes A, B.
A has SET of Bs.

MetaData:
<jdo>
<package name="org.jpox.test">
<class name="A" table="A">
<datastore-identity strategy="increment" column="JDOIDX"/>
<inheritance>
<discriminator strategy="class-name" column="JDOCLASSX"/>
</inheritance>
<version strategy="version-number" column="JDOLOCKX"/>
<field name="set" table="A_SET">
<collection element-type="B"/>
<join column="JDOIDX"/>
<element column="BX"/>
</field>
<field name="name" column="NAMEX"/>
</class>

<class name="B" table="B">
<datastore-identity strategy="increment" column="JDOIDX"/>
<inheritance>
<discriminator strategy="class-name" column="JDOCLASSX"/>
</inheritance>
<version strategy="version-number" column="JDOLOCKX"/>
<field name="name" column="NAMEX"/>
</class>

</package>
</jdo>


Query of form:
query = pm.newQuery(A.class, "set.contains(b)");
query.declareParameters( "org.jpox.test.B b" );

 
Erik's suggestion:

SELECT `THIS`.`JDOCLASSX`,`THIS`.`JDOIDX`,`THIS`.`JDOLOCKX`,`THIS`.`NAMEX`
    FROM `A` `THIS`
    WHERE EXISTS (
         SELECT 1 FROM `A_SET` `THIS_SET`,
                       `B` `THIS_SET_1`
                  WHERE `THIS_SET`.`JDOIDX` = `THIS`.`JDOIDX` AND
                       `THIS_SET_1`.`JDOIDX` = `THIS_SET`.`BX` AND
                       <1> = `THIS_SET_1`.`JDOIDX` AND
                       `THIS`.`JDOCLASSX` = <'org.jpox.test.A'>
                 )



could have been
 


SELECT `THIS`.`JDOCLASSX`,`THIS`.`JDOIDX`,`THIS`.`JDOLOCKX`,`THIS`.`NAMEX`
    FROM `A` `THIS`
    WHERE EXISTS (
         SELECT 1 FROM `A_SET` `THIS_SET`
WHERE `THIS_SET`.`JDOIDX` = `THIS`.`JDOIDX` AND
                        <1> = `THIS_SET`.`BX` AND
                        `THIS`.`JDOCLASSX` = <'org.jpox.test.A'>
                 )




Sort Order: Ascending order - Click to sort in descending order
Clive Cox added a comment - 24/Apr/06 02:37 PM
Provides a simple test bed to produce the bad SQL.

Andy Jefferson added a comment - 08/Jan/08 04:24 PM
The SQL produced by JPOX SVN is currently :-

SELECT `THIS`.`JDOCLASSX`,`THIS`.`JDOIDX`,`THIS`.`JDOLOCKX`,`THIS`.`NAMEX`
FROM `A` `THIS`
WHERE EXISTS (
    SELECT 1 FROM `A_SET` `THIS_SET` CROSS JOIN `B` `THIS_SET_1`
    WHERE `THIS_SET`.`JDOIDX` = `THIS`.`JDOIDX`
    AND `THIS_SET_1`.`JDOIDX` = `THIS_SET`.`BX`
    AND <1> = `THIS_SET_1`.`JDOIDX`
)

So what *exactly* is the problem with that and what do you expect it to be ?
You mention some forum thread yet when you raised the JIRA you didnt reference it. There is mention of use of the discrim above yet your testcase doesn't imply that this is necessary.

Andy Jefferson added a comment - 08/Jan/08 04:42 PM
Perhaps your point is the join to the B table is not really needed. Anyway, its an optimisation so moved to 1.3

Andy Jefferson added a comment - 23/Mar/09 12:32 PM
Query issues like this will not be addressed with the legacy JDOQL implementation; wait for "JDOQL2" to be complete

Andy Jefferson added a comment - 20/Jul/09 11:41 AM
JDOQL2 implementation in store.rdbms generates the following SQL for this testcase

SELECT A0.NAMEX,A0.JDOIDX,A0.JDOLOCKX,A0.JDOCLASSX
FROM A A0
INNER JOIN A_SET B0 ON B0.JDOIDX = A0.JDOIDX
INNER JOIN B C0 ON C0.JDOIDX = B0.BX
WHERE C0.JDOIDX = <1>

which is a lot simpler than the SQL you proposed :-P