简体   繁体   English

BeanPropertyRowMapper上的Java慢速SQL检索到ArrayList <accountQueryResult>

[英]Java Slow SQL retrieval on BeanPropertyRowMapper to ArrayList<accountQueryResult>

we have a very slow Java API function in SpringBoot framework, and follows is a profiling output of it: 我们在SpringBoot框架中有一个非常慢的Java API函数,下面是它的概要分析输出: 在此处输入图片说明

We believe this is coming from this line of code: 我们认为这来自以下代码行:

The query before that line, retrieves 41,573 rows (given specified accountId and one more parameter) - this is done in acceptable time of about 2 secs. 在该行之前的查询将检索41,573行(给定指定的accountId和一个以上的参数)-这是在大约2秒的可接受时间内完成的。

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

We tried to set the FetchSize to 1000 (it was set to -1 by default which I was unable to determine the meaning of in documentation) - this change did not improve the performance of the operation noticeably. 我们尝试将FetchSize设置为1000(默认情况下设置为-1,我无法确定文档中的含义)-此更改并未显着提高操作的性能。

One other suggestion was to switch to a HashMap structure instead of ArrayList, but I am not sure how to do that... tried to write a hash map, something like: 另一个建议是切换到HashMap结构而不是ArrayList,但是我不确定该怎么做...试图编写一个哈希映射,例如:

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

But this errors with Expression expected, I am not sure how to do it right. 但这是Expression的错误,我不确定如何正确执行。

This is the relevant piece of code for your review: 这是相关代码供您查看:

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

Follows is the accountQueryResult class which is currently used as mapper. 接下来是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
}

Please assist, how to change this one of the suggestions was using JPA, preferably with minimal changes as to avoid having to change all the business logic that processes the resulting array later.. 请协助,如何更改此建议之一是使用JPA,最好进行最小的更改,以避免以后更改处理结果数组的所有业务逻辑。

Thanks! 谢谢!

The first thing when tackling a performance question like this is to find out where the time is spent. 解决这样的性能问题时,第一件事就是找出花费的时间。

Given your profilers information, it strikes me as odd that getting the ints seems to take so much longer than getting the other fields. 有了您的探查器信息,让我感到奇怪的是,获取int似乎比获取其他字段花费的时间长得多。 I see following possible reasons: 我看到以下可能的原因:

  1. the getInt does some expensive conversion, eg the JDDBC driver might return BigDecimal which then have to get converted to int . getInt一些昂贵的转换,例如JDDBC驱动程序可能返回BigDecimal ,然后必须将其转换为int

  2. it is just the first column to get accessed and actually triggers fetching and spends lot's of time waiting. 它只是被访问的第一列,实际上触发了获取并花费大量时间等待。

For the overall performance another problem might be the use of reflection by BeanPropertyRowMapper but this doesn't even show up in the profiler so far. 对于整体性能,另一个问题可能是BeanPropertyRowMapper使用反射,但是到目前为止,它甚至没有出现在探查器中。

What I consider more likely is that the statement might return after 2 seconds but actually takes much longer to fetch all the results. 我认为更有可能的是,该语句可能会在2秒后返回,但实际上需要更长的时间才能获取所有结果。

To clarify the situation I'd recommend testing the following: 为了澄清这种情况,我建议您测试以下内容:

  1. Inspect the ResultSet returned by the JDBC driver for the datatypes it actually contains and check if you can get something more suitable out of it by changing column types or by casting in the SQL statement. 检查JDBC驱动程序返回的ResultSet实际包含的数据类型,并检查是否可以通过更改列类型或强制转换SQL语句从中获取更合适的结果。

  2. Obtain all the columns from all the rows without doing anything expensive with them. 从所有行中获取所有列,而无需对其进行任何昂贵的处理。 Just make sure the optimizer doesn't get rid of the access. 只要确保优化程序不会放弃访问权限即可。 For example you might want to create a hash from each value and add all hashes and print that at the end. 例如,您可能想根据每个值创建一个哈希,然后添加所有哈希并在最后打印出来。 Check the performance of that. 检查其性能。

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

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