2011-09-28 77 views
2

我有一個基於數據庫中索引字段執行簡單查詢的Hibernate/JPA查詢。這個表格相當大,大約有2800萬條記錄,但是當直接使用數據庫時,查詢會立即返回,而Hibernate + JPA則需要20秒以上。該數據庫是PostgreSQL 9.0.4。如何調試此Hibernate/JPA慢查詢問題?

這是包括相關查詢在內的日誌摘錄,從時間戳中可以看到發出查詢和打開ResultSet之間的長時間延遲。

2011-09-28 06:26:38,019 [http-thread-pool-8080(5)] DEBUG org.hibernate.jdbc.AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0) 
2011-09-28 06:26:38,019 [http-thread-pool-8080(5)] DEBUG org.hibernate.jdbc.ConnectionManager - opening JDBC connection 
2011-09-28 06:26:38,020 [http-thread-pool-8080(5)] DEBUG org.hibernate.SQL - select pafaddress0_.address_id as address1_0_, pafaddress0_.admin1 as admin2_0_, pafaddress0_.admin2 as admin3_0_, pafaddress0_.admin3 as admin4_0_, pafaddress0_.barcode as barcode0_, pafaddress0_.building_name as building6_0_, pafaddress0_.building_number as building7_0_, pafaddress0_.country_name as country8_0_, pafaddress0_.dependent_locality as dependent9_0_, pafaddress0_.dependent_street as dependent10_0_, pafaddress0_.dept_name as dept11_0_, pafaddress0_.double_dep_locality as double12_0_, pafaddress0_.dps as dps0_, pafaddress0_.mailsort as mailsort0_, pafaddress0_.org_name as org15_0_, pafaddress0_.pca_id as pca16_0_, pafaddress0_.pobox as pobox0_, pafaddress0_.postcode as postcode0_, pafaddress0_.postcode1 as postcode19_0_, pafaddress0_.postcode_type as postcode20_0_, pafaddress0_.street as street0_, pafaddress0_.su_org_indicator as su22_0_, pafaddress0_.subbuilding_name as subbuil23_0_, pafaddress0_.posttown as posttown0_, pafaddress0_.trad_county as trad25_0_, pafaddress0_.type as type0_, pafaddress0_.udprn as udprn0_ from paf pafaddress0_ where pafaddress0_.pca_id=? limit ? 
2011-09-28 06:27:01,897 [http-thread-pool-8080(5)] DEBUG org.hibernate.jdbc.AbstractBatcher - about to open ResultSet (open ResultSets: 0, globally: 0) 
2011-09-28 06:27:01,900 [http-thread-pool-8080(5)] DEBUG org.hibernate.jdbc.AbstractBatcher - about to close ResultSet (open ResultSets: 1, globally: 1) 
2011-09-28 06:27:01,900 [http-thread-pool-8080(5)] DEBUG org.hibernate.jdbc.AbstractBatcher - about to close PreparedStatement (open PreparedStatements: 1, globally: 1) 
2011-09-28 06:27:01,900 [http-thread-pool-8080(5)] DEBUG org.hibernate.jdbc.ConnectionManager - aggressively releasing JDBC connection 
201 

我的實體沒有複雜的關聯,日誌中沒有任何跡象顯示在這段漫長的延遲過程中發生了什麼。

@Entity 
@Table(name = "paf") 
@NamedQueries({ 
     @NamedQuery(name = "PafAddress.findByPcaId", query = "SELECT a FROM PafAddress a where a.pcaId=:pcaId ") 
}) 
public class PafAddress implements Serializable, Identifiable<Long> { 
    private static final long serialVersionUID = -5831210090000717285L; 

    @Id 
    @Column(name = "address_id") 
    private Long id; 

    private String postcode; 

    @Column(name = "posttown") 
    private String town; 

    @Column(name = "dependent_locality") 
    private String dependentLocality; 

    @Column(name = "double_dep_locality") 
    private String doubleDepLocality; 

    @Column(name = "street") 
    private String street; 

    @Column(name = "dependent_street") 
    private String dependentStreet; 

    @Column(name = "building_number") 
    private String buildingNumber; 

    @Column(name = "building_name") 
    private String buildingName; 

    @Column(name = "subbuilding_name") 
    private String subbuildingName; 

    @Column(name = "pobox") 
    private String pobox; 

    @Column(name = "dept_name") 
    private String deptName; 

    @Column(name = "org_name") 
    private String orgName; 

    @Column(name = "udprn") 
    private String udprn; 

    @Column(name = "postcode_type") 
    private String postcodeType; 

    @Column(name = "su_org_indicator") 
    private String suOrgIndicator; 

    @Column(name = "dps") 
    private String dps; 

    @Column(name = "postcode1") 
    private String postcode1; 

    @Column(name = "admin1") 
    private String admin1; 

    @Column(name = "admin2") 
    private String admin2; 

    @Column(name = "admin3") 
    private String admin3; 

    @Column(name = "trad_county") 
    private String tradCounty; 

    @Column(name = "country_name") 
    private String countryName; 

    @Column(name = "mailsort") 
    private String mailsort; 

    @Column(name = "barcode") 
    private String barcode; 

    @Column(name = "type") 
    private String type; 

    @Column(name = "pca_id") 
    private Double pcaId; 

    public PafAddress() { 
    } 

任何想法爲什麼這個查詢表現如此糟糕,或者我如何確定原因?

+0

RDBMS? SQL Serevr? –

+0

PostgreSQL - 將此信息添加到現在的問題。 – Phill

+0

您要查詢多少行? – beny23

回答

1

我發現這個問題:

我在PostgreSQL中啓用auto_explain對於這使我看到了查詢計劃在日誌查詢取> 1秒。 看到http://www.postgresql.org/docs/current/static/auto-explain.html

對於休眠/ JPA查詢:

Limit (cost=0.00..13.12 rows=2 width=469) 
    -> Seq Scan on paf pafaddress0_ (cost=0.00..943043.74 rows=143753 width=469) 
     Filter: ((pca_id)::double precision = 7912139::double precision) 

本地數據庫查詢:

          QUERY PLAN            
Limit (cost=0.00..7.03 rows=2 width=469) 
    -> Index Scan using paf_pca_idx on paf pafaddress0_ (cost=0.00..505649.83 rows=143753 width=469) 
     Index Cond: (pca_id = 7912139::numeric) 

因爲正在執行順序掃描代替的使用索引,看似因爲它是緩慢這是我的實體和數據庫字段之間類型不匹配的結果。實體屬性是「Double」,而數據庫類型是「數字」,查詢說明顯示數據庫字段的強制轉換髮生的翻倍double precision

我將數據庫字段類型更改爲double precision,查詢現在按預期執行。

0

如果sql是相同的,瓶頸必須是爲每個記錄創建單個Java對象的過程。我假設它會返回大量的記錄,您可以嘗試限制這個數字。