控制datanucleus如何创建查询

时间:2014-10-29 19:36:00

标签: java mysql jdo datanucleus

目前我正在使用datanucleus 4.0.2进行项目。 在一些表中,我有多达一百万行,这通常不是数据库处理的问题。

然而,当datanucleus获取所有依赖元素时,它将生成如下所示的查询:

SELECT 
    'my.com.CHILD_TABLE' AS NUCLEUS_TYPE,
    `CHILD_TABLE`.`ID` # And alot of more fields
FROM
    `CHILD_TABLE` 
WHERE
    EXISTS( SELECT DISTINCT
            'my.com.MIDDLE_TABLE' AS NUCLEUS_TYPE,
                `MIDDLE_TABLE`.`ID`
        FROM
            `MIDDLE_TABLE` 
               INNER JOIN
            `FIRST_TABLE` ON `MIDDLE_TABLE`.`MIDDLE_PARENT_ID_OID` = `FIRST_TABLE`.`ID`
        WHERE
            `FIRST_TABLE`.`TABLE_OWNER_ID_OID` = 5057520
                AND `CHILD_TABLE`.`PARENT_ID_OID` = `MIDDLE_TABLE`.`ID`)

出于某种原因,mysql需要扫描子表中的所有100万行。 (这可能是查询执行计划程序错误)

将其转换为此表格

SELECT 
    'my.com.CHILD_TABLE' AS NUCLEUS_TYPE,
    `CHILD_TABLE`.`ID`
FROM
    `CHILD_TABLE` 
INNER JOIN `MIDDLE_TABLE` 
    ON `CHILD_TABLE`.`PARENT_ID_OID` = `MIDDLE_TABLE`.`ID`
               INNER JOIN
            `FIRST_TABLE` ON `MIDDLE_TABLE`.`MIDDLE_PARENT_ID_OID` = `FIRST_TABLE`.`ID`
        WHERE
            `FIRST_TABLE`.`TABLE_OWNER_ID_OID` = 5057520

给出神奇的结果,只需要扫描9行或类似的行。

是否可以控制datanucleus如何生成这些查询?

聚苯乙烯。我找到了一个相关的帖子,在存在http://solutionfactor.net/blog/2011/11/06/mysql-inner-join-vs-exists-may-yield-better-performance/

时用mysql解释问题

使用某些代码更新了问题 以下是实体关系的设置方式:

@PersistenceCapable(detachable = "true", identityType = IdentityType.APPLICATION)
class ChildTable {
    @PrimaryKey
    private Long id;
    MiddleTable middleTable;
    // More fields
}

@PersistenceCapable(detachable = "true", identityType = IdentityType.APPLICATION)
class MiddleTable {
    @PrimaryKey
    private Long id;
    ParentTable parentTable;
    @Persistent(mappedBy="middleTable", defaultFetchGroup="true")
    private Set<ChildTable> children;

}
@PersistenceCapable(detachable = "true", identityType = IdentityType.APPLICATION)
class ParentTable {
    @PrimaryKey
    private Long id;

    MasterTable masterTable;
    @Persistent(mappedBy="parentTable")
    private Set<MiddleTable> children;
 }

// Master table code is left out for brewety, same set up

Query query = pm.newQuery(MiddleTable.class);
Collection<MiddleTable> entitySet;

try {
    query.setFilter("parentTable.masterTable == :masterTable");
    entitySet = (Collection<MiddleTable>) query.execute(masterTable);

}
finally {
    query.closeAll();
}

基本上这里发生的是执行查询时datanucleus还将执行两个本机查询。 第一个效果很好。它看起来像我发布的第一个原始查询,除了EXISTS的东西。

启动第二个,因为子项位于默认的提取组中。这就是我想减少查询次数的方法。稍后将访问所有儿童。

0 个答案:

没有答案