2012-03-13 98 views
1

我有一个MySQL表,用于持久化一些Java对象并使用Hibernate来映射数据/列。对象/表格包含大约50列/字段。在表面上,并在最小的负载下这工作正常,但我遇到了程序启动时的问题,我从表中加载所有可用的对象。表中目前大约有8500行。加载这些行需要很长的时间,超过5分钟!显然这是不对的,我必须在我的Hibernate配置(或其他地方)做一些可怕的错误。对于使用java.sql。*包的所有行的普通查询大约需要300 ms来检索8000多行,这是可以接受的,但理想情况下,我希望保留Hibernate的映射功能。Java MySQL Hibernate缓慢选择查询

我在下面附加了Hibernate的主要配置。我很乐意提供进一步的配置/实现细节,但我不想在这个阶段用什么可能是不必要的信息来膨胀这个问题。

<hibernate-configuration> 
<session-factory> 
    <property name="hibernate.connection.driver_class"> 
    com.mysql.jdbc.Driver</property> 
    <property name="hibernate.connection.url"> 

jdbc:mysql://127.0.0.1:3306/abc</property> 
    <property name="hibernate.connection.username">user</property> 
    <property name="hibernate.connection.password">password</property> 

    <property name="org.hibernate.SQL">true</property> 
    <property name="dialect">org.hibernate.dialect.MySQLDialect</property> 
    <property name="hibernate.hbm2ddl.auto">update</property> 

    <property name="hibernate.c3p0.idle_test_period">60</property> 
    <property name="hibernate.c3p0.min_size">5</property> 
    <property name="hibernate.c3p0.max_size">20</property> 
    <property name="hibernate.c3p0.max_statements">250</property> 
    <property name="hibernate.c3p0.timeout">1800</property> 
    <property name="hibernate.c3p0.acquireRetryAttempts">1</property> 
    <property name="hibernate.c3p0.acquireRetryDelay">250</property> 

    <property name= "hibernate.transaction.factory_class"> 
     org.hibernate.transaction.JDBCTransactionFactory 
    </property> 
    <property name="hibernate.current_session_context_class">thread</property> 

我最初使用默认的连接池,而是尝试切换到C3P0在希望它能帮助,但无论池行的加载时间基本相同。

很显然,我不是一个Hibernate专家,所以我真的很感谢一些见解,我做错了什么。谢谢。

UPDATE1 从查询中添加日志输出。

20:16:40,633 DEBUG QueryTranslatorImpl:283 - --- HQL AST --- 
    \-[QUERY] Node: 'query' 
     +-[SELECT_FROM] Node: 'SELECT_FROM' 
     | \-[FROM] Node: 'from' 
     |  \-[RANGE] Node: 'RANGE' 
     |  \-[DOT] Node: '.' 
     |   +-[DOT] Node: '.' 
     |   | +-[DOT] Node: '.' 
     |   | | +-[DOT] Node: '.' 
     |   | | | +-[IDENT] Node: 'com' 
     |   | | | \-[IDENT] Node: 'xyz' 
     |   | | \-[IDENT] Node: 'objects' 
     |   | \-[IDENT] Node: 'abc' 
     |   \-[IDENT] Node: 'ObjectID' 
     \-[WHERE] Node: 'where' 
      \-[EQ] Node: '=' 
       +-[IDENT] Node: 'event_id' 
       \-[NUM_INT] Node: '1331570489282' 

20:16:40,633 DEBUG QueryTranslatorImpl:252 - --- SQL AST --- 
\-[SELECT] QueryNode: 'SELECT' querySpaces (order_log) 
    +-[SELECT_CLAUSE] SelectClause: '{derived select clause}' 
    | +-[SELECT_EXPR] SelectExpressionImpl: 'objectid0_.event_id as abc1_0_' {FromElement{explicit,not a collection join,not a fetch join,fetch non-lazy properties,classAlias=null,role=null,tableName=order_log,tableAlias=objectid0_,origin=null,columns={,className=com.xyz.objects.abc.objectid}}} 
    | \-[SQL_TOKEN] SqlFragment: 'objectid0_.order_id as abc2_0_, objectid0_.order_id as order3_0_, objectid0_.px_cond as px4_0_, objectid0_.px_curr as px5_0_, objectid0_.px_value as px6_0_, objectid0_.vol_cond as vol7_0_, objectid0_.vol as vol0_, objectid0_.side as side0_, objectid0_.trd_vol as trd10_0_, objectid0_.open_vol as open11_0_, objectid0_.accno as accno0_, objectid0_.symbol as symbol0_, objectid0_.market as market0_, objectid0_.validity_type as validity15_0_, objectid0_.validity_date as validity16_0_, objectid0_.mod_date as mod17_0_, objectid0_.result_code as result18_0_, objectid0_.order_state as order19_0_, objectid0_.action_state as action20_0_, objectid0_.action_type as action21_0_, objectid0_.action_status as action22_0_, objectid0_.status_text as status23_0_, objectid0_.strategy_id as strategy24_0_, objectid0_.passive as passive0_, objectid0_.timestamp as timestamp0_, objectid0_.confirmedorder as confirm27_0_, objectid0_.updatesource as updates28_0_' 
    +-[FROM] FromClause: 'from' FromClause{level=1, fromElementCounter=1, fromElements=1, fromElementByClassAlias=[], fromElementByTableAlias=[objectid0_], fromElementsByPath=[], collectionJoinFromElementsByPath=[], impliedElements=[]} 
    | \-[FROM_FRAGMENT] FromElement: 'order_log objectid0_' FromElement{explicit,not a collection join,not a fetch join,fetch non-lazy properties,classAlias=null,role=null,tableName=order_log,tableAlias=objectid0_,origin=null,columns={,className=com.abc.objects.xyz.objectid}} 
    \-[WHERE] SqlNode: 'where' 
     \-[EQ] BinaryLogicOperatorNode: '=' 
      +-[IDENT] IdentNode: 'event_id' {originalText=event_id} 
      \-[NUM_INT] LiteralNode: '1331570489282' 

在日志中有很多输出,但我认为上面的2个项目是最相关的。如果我错过了重要的事情,请告诉我。

UPDATE2添加实际的sql输出。

Hibernate: /* from objectid where abc_event_id=1331570505614 */ select objectid0 
_.abc_event_id as abc1_0_, objectid0_.abc_order_id as abc2_0_, objectid0_. 
order_id as order3_0_, objectid0_.px_cond as px4_0_, objectid0_.px_curr as px5_0_, 
objectid0_.px_value as px6_0_, objectid0_.vol_cond as vol7_0_, objectid0_.vol as v 
ol0_, objectid0_.side as side0_, objectid0_.trd_vol as trd10_0_, objectid0_.open_vo 
l as open11_0_, objectid0_.accno as accno0_, objectid0_.symbol as symbol0_, ucorde 
r0_.market as market0_, objectid0_.validity_type as validity15_0_, objectid0_.vali 
dity_date as validity16_0_, objectid0_.mod_date as mod17_0_, objectid0_.result_cod 
e as result18_0_, objectid0_.order_state as order19_0_, objectid0_.action_state as 
action20_0_, objectid0_.action_type as action21_0_, objectid0_.action_status as a 
ction22_0_, objectid0_.status_text as status23_0_, objectid0_.strategy_id as strat 
egy24_0_, objectid0_.passive as passive0_, objectid0_.timestamp as timestamp0_, uc 
order0_.confirmedorder as confirm27_0_, objectid0_.updatesource as updates28_0_ f 
rom order_log objectid0_ where abc_event_id=1331570505614 

UPDATE 3对象映射+事务代码

<hibernate-mapping> 
    <class name="com.abc.objects.xyz.objectid" table="order_log"> 
    <id name="EventId" type="long" column="event_id" > 
    <generator class="assigned"/> 
    </id> 

    <property name="ordId"> 
    <column name="order_id"/> 
    </property> 
    <property name="pxCond"> 
    <column name="px_cond"/> 
    </property> 
... 
</hibernate-mapping> 

映射是摘录,但它是直线前进沿着相同的路线如上。查询表的交易如下所示:

Session session = HibernateUtil.getSessionFactory().openSession(); 
org.hibernate.Transaction transaction = null; 
try { 
    long t0 = System.currentTimeMillis(); 
    transaction = session.beginTransaction(); 
    List<UCOrder> result = session.createQuery("from UCOrder").list(); 
    transaction.commit(); 
    System.out.println (result.size() + " rows were retrieved"); 
    System.out.println("Time elapsed: " + (System.currentTimeMillis()-t0)); 
} catch (Exception e) { 
    transaction.rollback(); 
    e.printStackTrace(); 
} finally { 
    session.close(); 
} 

也很直截了当我想想?!?。然而,它需要检索数据的时间千倍相比,如下图所示香草java.sql.*方法:

Connection conn = DriverManager.getConnection (url, userName, password); 
Statement s = conn.createStatement(); 
s.executeQuery ("SELECT * FROM order_log"); 
ResultSet rs = s.getResultSet(); 
+0

Hibernate配置本身都很好看。你能展示实际执行查询的Hibernate代码吗?正如jabal所说,hibernate.show_sql也是一个好主意。 – derdc 2012-03-13 19:04:04

+0

谢谢。我在上面添加了一些日志输出。 – hgus1294 2012-03-13 19:35:41

+0

对于我来说,HQL AST有点太多以至于无法发现任何问题;)请仅发布由Hibernate生成的相关SQL查询,以便使用'hibernate.show_sql = true'和'hibernate.format_sql = true'来记录它们。 – tscho 2012-03-13 19:52:08

回答

1

,我建议你在Hibernate的一个详细日志记录开关。你可以得到它来记录所有的SQL查询,看看它们中是否有不寻常的东西。要做到这一点

一种方法是设置hibernate.show_sqltrue和/或(?)配置Hibernate使用的输出所有org.hibernate类你喜欢的输出文件共享记录。

+0

谢谢。我已经为'org.hibernate = ALL'设置了log4j设置,这给了我很多输出。其中大部分对我来说是希腊语,但我注意到它指定了所有字段(即'SELECT field1,field2,...',而不是用通配符('*')选择。我不知道是否可以改变或者如果它会有所作为 – hgus1294 2012-03-13 19:12:29

+0

不是真的解决(*)字段名是数据库我猜的第一件事情之一Hibernate生成的SQL不太好看,但性能问题的答案应该隐藏那么 – jabal 2012-03-13 19:17:05

+0

也许你可以复制查询并用MySQL工具分析它们以找到瓶颈 – jabal 2012-03-13 19:17:44

0

您不需要在“选择”中进行交易。 如果您使用log4j,请禁用对休眠的调试。 申请关联表“模式懒惰”。这个非常重要。