2017-08-04 59 views
0

我們在SpringBoot框架非常緩慢的Java API函數,下面是它的一個剖析輸出: enter image description here的Java慢SQL檢索到的ArrayList <accountQueryResult>

我們相信這是從該行的來臨代碼:

那行之前的查詢,檢索41573行(給定的指定帳戶ID和一個參數) - 這是在可接受的約2秒的時間內完成。

return (ArrayList) this.pbaJdbc.query(sql, new Object[] { accountId, taxRegId }, bpm); 

我們試圖將FETCHSIZE設置爲1000(它被設置爲-1默認情況下,我無法確定文件的意思) - 這種變化並沒有顯着提高操作的性能。其他

一個建議是切換到一個HashMap的結構,而不是ArrayList的,但我不知道該怎麼做......試着寫一個哈希表,是這樣的:

HashMap<Integer, accountQueryResult> accmap = new HashMap(Integer, accountQueryResult); 

但這個錯誤預計表達,我不知道怎麼做是正確的。

這是您的評論相關的代碼:

@Repository 
public class UserRepository { 
    @Autowired 
    @Qualifier("pbaJdbc") 
    private JdbcTemplate pbaJdbc; 

    public ArrayList<accountQueryResult> getAccountsSubscriptionsResources(int accountId, String taxRegId) { 

     BeanPropertyRowMapper bpm = new BeanPropertyRowMapper(accountQueryResult.class); 
     bpm.setPrimitivesDefaultedForNullValue(true); 
     String sql = 

       "SELECT " + 
         "\"Account\".\"AccountID\",\n" + 
         "\"Account\".\"VendorAccountID\",\n" + 
         "\"Account\".\"AdminPhAreaCode\",\n" + 
         "\"Account\".\"AdminPhNumber\",\n" + 
         "\"Account\".\"AdminFaxAreaCode\",\n" + 
         "\"Account\".\"AdminFaxNumber\",\n" + 
         "\"Account\".\"AdminEmail\",\n" + 
         "\"Account\".\"PersPhAreaCode\",\n" + 
         "\"Account\".\"PersPhNumber\",\n" + 
         "\"Account\".\"PersFaxAreaCode\",\n" + 
         "\"Account\".\"PersFaxNumber\",\n" + 
         "\"Account\".\"PersEmail\",\n" + 
         "\"Account\".\"TaxStatus\",\n" + 
         "\"Account\".\"CompanyName\",\n" + 
         "\"Account\".\"Address1\",\n" + 
         "\"Account\".\"Address2\",\n" + 
         "\"Account\".\"City\",\n" + 
         "\"Account\".\"Zip\",\n" + 
         "\"ActivePaytool\".\"CutNumber\",\n" + 
         "\"ActivePaytool\".\"PaySystem\",\n" + 
         "\"Subscription\".\"subscriptionID\",\n" + 
         "\"Subscription\".\"SubscriptionName\",\n" + 
         "\"Subscription\".\"Status\",\n" + 
         "\"Subscription\".\"PlanID\",\n" + 
         "\"PlanPeriod\".\"Period\",\n" + 
         "\"PlanPeriod\".\"PlanPeriodID\",\n" + 
         "\"PlanPeriod\".\"PeriodType\",\n" + 
         "\"PlanPeriod\".\"RenewalFee\",\n" + 
         "\"PlanPeriod\".\"SetupFee\",\n" + 
         "\"SubscrParam\".\"resourceID\",\n" + 
         "\"BMResource\".\"name\" AS \"ResourceName\",\n" + 
         "\"SubscrParam\".\"IncludedValue\",\n" + 
         "\"SubscrParam\".\"Amount\",\n" + 
         "\"SubscrParamValue\".\"IdParameter\",\n" + 
         "\"SubscrParamValue\".\"Value\",\n" + 
         "\"IntUsers\".\"UsersID\",\n" + 
         "\"IntUsers\".\"Login\" AS \"LoginID\"\n" + 
         "FROM\n" + 
         "\"Account\"\n" + 
         "LEFT JOIN \"IntUsers\" ON \"IntUsers\".\"AccountID\" = \"Account\".\"AccountID\"\n" + 
         "LEFT JOIN \"Subscription\" ON \"Subscription\".\"AccountID\" = \"Account\".\"AccountID\"\n" + 
         "AND \"Subscription\".\"Status\" IN ('30', '40', '15')\n" + 
         "LEFT JOIN \"SubscrParam\" ON \"SubscrParam\".\"subscriptionID\" = \"Subscription\".\"subscriptionID\"\n" + 
         "LEFT JOIN \"BMResource\" ON \"BMResource\".\"resourceID\" = \"SubscrParam\".\"resourceID\"\n" + 
         "LEFT JOIN \"SubscrParamValue\" ON \"SubscrParamValue\".\"subscriptionID\" = \"Subscription\".\"subscriptionID\"\n" + 
         "LEFT JOIN \"PlanPeriod\" ON \"PlanPeriod\".\"PlanID\" = \"Subscription\".\"PlanID\"\n" + 
         "AND NOT (\n" + 
         "\"Subscription\".\"Period\" = \"PlanPeriod\".\"Period\"\n" + 
         "AND \"Subscription\".\"PeriodType\" = \"PlanPeriod\".\"PeriodType\"\n" + 
         ")\n" + 
         "AND \"PlanPeriod\".\"Enabled\" = 1\n" + 
         "AND \"PlanPeriod\".\"Trial\" = 0\n" + 
         "LEFT JOIN (\n" + 
         "SELECT\n" + 
         " \"DefPayTool\".\"PayToolID\",\n" + 
         " \"PayTool\".\"CutNumber\",\n" + 
         " \"PayTool\".\"PaySystem\",\n" + 
         " \"PayTool\".\"OwnerAccountID\"\n" + 
         "FROM\n" + 
         " \"PayTool\"\n" + 
         "INNER JOIN \"DefPayTool\" ON \"DefPayTool\".\"AccountID\" = \"PayTool\".\"OwnerAccountID\"\n" + 
         "WHERE\n" + 
         " \"PayTool\".\"IsSuspended\" = 0\n" + 
         "GROUP BY\n" + 
         " \"PayTool\".\"PayToolID\",\n" + 
         " \"PayTool\".\"CutNumber\",\n" + 
         " \"PayTool\".\"PaySystem\",\n" + 
         " \"PayTool\".\"OwnerAccountID\",\n" + 
         " \"DefPayTool\".\"PayToolID\"\n" + 
         "HAVING\n" + 
         " COUNT (*) > 0\n" + 
         ") AS \"ActivePaytool\" ON \"ActivePaytool\".\"OwnerAccountID\" = \"Account\".\"AccountID\"\n" + 
         "WHERE\n" + 
         "\"Account\".\"AccountID\" = ? " + 
         "AND \"Account\".\"TaxRegID\" = ? " + 
         "ORDER BY\n" + 
         "\"Account\".\"AccountID\",\n" + 
         "\"Subscription\".\"subscriptionID\";"; 

     return (ArrayList) this.pbaJdbc.query(sql, new Object[] { accountId, taxRegId }, bpm); 
    } 

以下是其目前被用作映射器accountQueryResult類。

package com.store.models.query; 

public class accountQueryResult { 
    private int AccountID; 

    private int VendorAccountID; 

    private String CompanyName; 

    private String AdminPhAreaCode; 

    private String AdminPhNumber; 

    private String AdminFaxAreaCode; 

    private String AdminFaxNumber; 

    private String AdminEmail; 

    private String PersPhAreaCode; 

    private String PersPhNumber; 

    private String PersFaxAreaCode; 

    private String PersFaxNumber; 

    private String PersEmail; 

    private int TaxStatus; 

    private String CutNumber; 

    private String PaySystem; 

    private int subscriptionID; 

    private String SubscriptionName; 

    private int Status; 

    private int PlanID; 

    private int resourceID; 

    private String ResourceName; 

    private int IncludedValue; 

    private int Amount; 

    private String IdParameter; 

    private String Value; 

    private int UsersID; 

    private String LoginID; 

    private String Address1; 

    private String Address2; 

    private String City; 

    private String Zip; 

    private int period; 

    private int planPeriodID; 

    private int periodType; 

    private double renewalFee; 

    private double setupFee; 

// Ommited getter and setters 
} 

請幫助,如何改變這種的建議之一是使用JPA,最好用最小的變化,以避免改變了這一切後處理得到的陣列業務邏輯..

謝謝!

+0

可能轉換爲使用JPA(preparedStaement)而不是jdbctemplate –

+0

嗯,它會提高性能嗎?我不需要手動將結果映射到對象上,手動映射後最終回到相同的問題? – Carmageddon

+0

即使使用41K行,也不需要6秒即可從ResultSet中獲取Int - 我只是建議您嘗試JPA,因爲這可能看起來像是一個'BeanPropertyRowMapper' –

回答

0

解決這樣的性能問題的第一件事是找出時間花在哪裏。

鑑於您的配置文件信息,讓我感到奇怪的是,獲取整數看起來比獲取其他字段花費的時間要長得多。我看到以下可能的原因:

  1. getInt會進行一些昂貴的轉換,例如,在JDDBC驅動程序可能返回BigDecimal然後必須得到轉換爲int

  2. 它只是第一列被訪問,實際上觸發器獲取並花費很多時間等待。

對於整體性能的另一個問題可能是由BeanPropertyRowMapper使用反射但這並不甚至在探查顯示出來爲止。

我認爲更可能的是該語句可能會在2秒後返回,但實際需要更長時間才能獲取所有結果。

爲了澄清我建議你測試情況如下:

  1. 檢查由JDBC驅動程序,它實際上包含了數據類型返回的ResultSet和檢查,如果你能得到的東西更適合出它通過更改列類型或通過在SQL語句中轉換。

  2. 從所有行中獲取所有列,而無需執行任何昂貴的操作。只要確保優化器沒有擺脫訪問。例如,您可能希望從每個值創建一個散列,並添加所有散列並在最後打印。檢查它的性能。

相關問題