我有一個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();
Hibernate配置本身都很好看。你能展示實際執行查詢的Hibernate代碼嗎?正如jabal所說,hibernate.show_sql也是一個好主意。 – derdc 2012-03-13 19:04:04
謝謝。我在上面添加了一些日誌輸出。 – hgus1294 2012-03-13 19:35:41
對於我來說,HQL AST有點太多以至於無法發現任何問題;)請僅發佈由Hibernate生成的相關SQL查詢,以便使用'hibernate.show_sql = true'和'hibernate.format_sql = true'來記錄它們。 – tscho 2012-03-13 19:52:08