apache derby挂起执行查询

时间:2011-10-31 22:08:01

标签: sql derby

我真的很感激这里的一些帮助。 我从我的客户那里得到了这个derby数据库,他们的应用程序基于Hibernate。我无法使它工作,因为Hibernate生成挂起整个数据库的查询:

select houses0_.STREET_ID as STREET5_1_, houses0_.ID as ID1_, houses0_.ID as ID42_0_, houses0_.NAME as NAME42_0_, houses0_.SHORT_NAME as SHORT3_42_0_, houses0_.INDEX as INDEX42_0_ from SRG.HOUSE_REFERENCE houses0_ where houses0_.STREET_ID in (select streets0_.ID from SRG.STREET_REFERENCE streets0_ where streets0_.TOWNSHIP_ID in (select townships0_.ID from SRG.TOWNSHIP_REFERENCE townships0_ where townships0_.CITY_ID='555'))

我没有看到任何可疑的东西,但当我用它发动德比时 - 德比什么也没做。这是我的日志:

 2011-10-31 21:58:10.328 GMT Thread[DRDAConnThread_3,5,main] (XID = 1152939), (SESSIONID = 1), (DATABASE = dev), (DRDAID = NF000001.FC97-434877518919679629{1}), Begin compiling prepared statement: select houses0_.STREET_ID as STREET5_1_, houses0_.ID as ID1_, houses0_.ID as ID42_0_, houses0_.NAME as NAME42_0_, houses0_.SHORT_NAME as SHORT3_42_0_, houses0_.INDEX as INDEX42_0_ from HOUSE_REFERENCE houses0_ where houses0_.STREET_ID in (select streets0_.ID from STREET_REFERENCE streets0_ where streets0_.TOWNSHIP_ID in (select townships0_.ID from TOWNSHIP_REFERENCE townships0_ where townships0_.CITY_ID='555')) :End prepared statement
2011-10-31 21:58:10.682 GMT Thread[DRDAConnThread_3,5,main] (XID = 1152939), (SESSIONID = 1), (DATABASE = dev), (DRDAID = NF000001.FC97-434877518919679629{1}), End compiling prepared statement: select houses0_.STREET_ID as STREET5_1_, houses0_.ID as ID1_, houses0_.ID as ID42_0_, houses0_.NAME as NAME42_0_, houses0_.SHORT_NAME as SHORT3_42_0_, houses0_.INDEX as INDEX42_0_ from SRG.HOUSE_REFERENCE houses0_ where houses0_.STREET_ID in (select streets0_.ID from SRG.STREET_REFERENCE streets0_ where streets0_.TOWNSHIP_ID in (select townships0_.ID from SRG.TOWNSHIP_REFERENCE townships0_ where townships0_.CITY_ID='555')) :End prepared statement
2011-10-31 21:58:10.758 GMT Thread[DRDAConnThread_3,5,main] (XID = 1152939), (SESSIONID = 1), (DATABASE = dev), (DRDAID = NF000001.FC97-434877518919679629{1}), Executing prepared statement: select houses0_.STREET_ID as STREET5_1_, houses0_.ID as ID1_, houses0_.ID as ID42_0_, houses0_.NAME as NAME42_0_, houses0_.SHORT_NAME as SHORT3_42_0_, houses0_.INDEX as INDEX42_0_ from SRG.HOUSE_REFERENCE houses0_ where houses0_.STREET_ID in (select streets0_.ID from SRG.STREET_REFERENCE streets0_ where streets0_.TOWNSHIP_ID in (select townships0_.ID from SRG.TOWNSHIP_REFERENCE townships0_ where townships0_.CITY_ID='555')) :End prepared statement

之后没事。 我设置了一些属性:

derby.drda.portNumber=1529

derby.locks.deadlockTrace=true
derby.locks.monitor=true

derby.locks.deadlockTimeout=1
derby.locks.waitTimeout=1

derby.language.logStatementText=false
derby.infolog.append=true

derby.stream.error.logSeverityLevel=0

derby.drda.logConnections=true

derby.language.logStatementText=true

derby.language.logQueryPlan=true

看看最新情况,但日志中没有任何内容,这个查询只需要永久执行,无论是从hibernate还是squirrelsql或者derby的ij工具完成的。 正如你所看到的,超时非常小,但德比不会停止执行查询,它会让它做任何查询所需的事情。

查询并不复杂 - 我使用连接重写了它,并且执行需要1秒。但不是那种形式 - 我不明白,为什么?你能给我一些提示吗?

UPD :house_reference包含7508行,从house_reference中选择*只需不到一秒,street_reference包含~44k行和子查询

select streets0_.ID from STREET_REFERENCE streets0_ where streets0_.TOWNSHIP_ID in (select townships0_.ID from TOWNSHIP_REFERENCE townships0_ where townships0_.CITY_ID='52000001000')

在不到一秒的时间内返回111行。所以选择* from house_reference with in子句包含111行需要 22 分钟来执行,并返回0结果。这对我来说看起来不错,但我不是在数据库管理方面有经验来判断,这就是为什么我要求社区:)

1 个答案:

答案 0 :(得分:0)

指定“in(子查询)”的查询不能总是替换为相应的连接。此过程称为“展平”,并且数据库必须遵循规则才能给出正确的答案。请参阅此文档:http://db.apache.org/derby/docs/10.8/tuning/ctuntransform36368.html

不幸的是,连接中的子查询存在严重的性能问题并不罕见。我很高兴您找到了一种解决方法(假设您重写的查询实际上是一种可接受的解决方法)。

对象关系映射库可以生成一些复杂的查询。如果您可以让查询最终运行,您可以从查询计划中学到一些东西。

另一种可能性是数据库统计信息变得不准确,导致Derby选择了一个糟糕的查询计划。最新版本的Derby改进了对重新计算统计数据的支持,这可以帮助优化器选择更好的查询计划。

http://db.apache.org/derby/docs/10.8/tuning/index.html

的Derby Tuning指南中有大量信息