简体   繁体   English

Java MySQL Hibernate慢选择查询

[英]Java MySQL Hibernate slow select queries

I have a MySQL table for persistence of some Java objects and use Hibernate for mapping of data/columns. 我有一个用于保留某些Java对象的MySQL表,并使用Hibernate映射数据/列。 The objects/table contain around 50 columns/fields. 对象/表包含大约50列/字段。 On the surface and under minimal load this works fine but I have run into problems on startup of the program where I load all available objects from the table. 从表面上看,在最小负载下可以正常工作,但是我在程序启动时遇到了问题,在该程序中我从表中加载了所有可用对象。 There is currently around 8500 rows in the table. 表格中目前大约有8500行。 The loading of these rows takes painfully long, in excess of 5 minutes!. 这些行的加载耗时很长,超过5分钟! Obviously this isn't right and I must have done something horribly wrong in my Hibernate configuration (or elsewhere). 显然这是不对的,我必须在Hibernate配置(或其他配置)中做一些可怕的错误。 A normal query for all rows using the java.sql.* package takes around 300 ms to retrieve the 8000+ rows which is acceptable, but ideally I would like to keep Hibernate for its mapping functionality. 使用java.sql。*包对所有行进行常规查询大约需要300毫秒才能检索8000多个行,但是理想情况下,我希望保留Hibernate的映射功能。

I have attached the main configuration for Hibernate below. 我在下面附加了Hibernate的主要配置。 I am happy to provide further configuration/implementation details but I do not want to bloat this question with what may be unnecessary information at this stage. 我很乐意提供进一步的配置/实现细节,但是我不想在这个阶段用什么可能是不必要的信息来夸大这个问题。

<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>

I was originally using the default connection pool but tried switching to C3P0 in hope that it would help but the loading time of the rows is basically the same regardless of pool. 我最初使用的是默认连接池,但尝试切换到C3P0希望对您有所帮助,但无论连接池如何,行的加载时间基本相同。

Obviously I am anything but a Hibernate expert so I would really appreciate some insight to what I am doing wrong. 显然,我除了Hibernate专家以外,什么都没有,所以我非常感谢您对我做错的事情有所了解。 Thanks. 谢谢。

UPDATE1 Adding log output from the queries. 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'

There is a lot more output in the logs but I figured that the 2 items above were the most relevant. 日志中还有很多输出,但是我认为上面的2个项目最相关。 If I have missed anything important, please let me know. 如果我错过任何重要事项,请告诉我。

UPDATE2 Adding the actual sql-output. 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 Object Mapping + Transaction code 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>

The mapping is an excerpt but it is straight forward along the same lines as above. 该映射是摘录,但沿与上述相同的直线是直接的。 The Transaction that queries the table looks like below: 查询表的事务如下所示:

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();
}

Also rather straight forward I would like to think?!?. 我也想直截了当?!?。 However, the time it takes to retrieve the data is thousandfold compared to the vanilla java.sql.* method illustrated below: 但是,与如下所示的普通java.sql.*方法相比,检索数据所需的时间是数千倍:

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

I suggest you switching on a verbose logging in Hibernate. 我建议您在Hibernate中打开详细的日志记录。 You can get it to log all SQL queries and see if there is something unusual in them. 您可以获取它来记录所有SQL查询,并查看其中是否存在异常。

One way to do this is setting hibernate.show_sql to true and/or (?) configure commons-logging used by Hibernate to output all org.hibernate category to your favourite output file. 一种方法是将hibernate.show_sql设置为true和/或(?)配置Hibernate用来将所有org.hibernate类别输出到您喜欢的输出文件的commons-logging。

You don't no need transaction in "select". 您不需要在“选择”中进行交易。 if you using log4j, please, disable debug for the hibernate. 如果使用log4j,请禁用休眠的调试功能。 Apply for association table "mode lazy". 申请关联表“懒惰模式”。 This is very important. 这个非常重要。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM