ResultSet Parser太慢

时间:2016-08-17 09:43:09

标签: java jdbc time

我需要从之前的查询中解析一个巨大的ResultSet,我想出了一些东西,但它太慢了。

public LinkedList<CountryFirstData> sortCountryFirst() throws SQLException {

    long parsingStart = System.nanoTime();


    LinkedList<CountryFirstData> list = new LinkedList<CountryFirstData>();

    String serie;
    String unit;
    String country;
    BigDecimal value;
    int year;
    int index;

    while (rs.next()) {

        serie = rs.getString(1); // rs is the previously built resultSet
        unit = rs.getString(2);
        country = rs.getString(3);
        value = rs.getBigDecimal(4);
        year = rs.getInt(5);
        if ((index = list.indexOf(new CountryFirstData(country, serie, unit))) != -1) {

            list.get(index).getDuo().add(new YearValueDuo(year, value));

        }
        else {

            CountryFirstData data = new CountryFirstData(country, serie, unit);
            data.getDuo().add(new YearValueDuo(year, value));
            list.add(data);

        }



    }
    long parsingEnd = System.nanoTime();

    Collections.sort(list);

    long sortEnd = System.nanoTime();


    System.out.println("Parsing Time = " + ((parsingEnd - parsingStart)/1000000000)); // gives 112s
    System.out.println("Sorting Time = " + ((sortEnd - parsingEnd)/1000000000)); // gives 0s


    return list;

}

我会尝试解释一下代码:

resultSet列包含5个不同的值。要考虑的第一个三重奏由countryserieunit组成。当我第一次得到这样的三重奏(else情况)时,我需要创建一个新的CountryFirstData并将结果集行中的剩余二人年/值添加到YearValueDuo列表字段中。创建了对象。

countryserie案例中)已经存在三个unitlistif时,我需要检索它并添加二重奏年/值到YearValueDuo列表。

因此,基本上,resultSet rs长度为4000行,整个解析(排除排序)需要2分钟。我觉得这只有4k线太多了。排序仍然很快(不到一秒钟)。

我在LinkedList上为CountryFirstData选择ArrayList,因为稍后我会在文件中按顺序写出整个列表(这很快)。

你们可以建议我一些改进吗?

1 个答案:

答案 0 :(得分:1)

一个List,实际上是一个Set(没有双打),然后排序。并返回实现类,强制进一步使用该类型,防止实现更改。

public Set<CountryFirstData> sortCountryFirst() throws SQLException {

    long parsingStart = System.nanoTime();

    SortedMap<CountryFirstData, CountryFirstData> identityMap = new TreeMap<>();
    //      Comparator.comparing(CountryFirstData::getCountry)
    //          .thenComparing(CountryFirstData::getSerie))
    //          .thenComparing(CountryFirstData::getUnit));

    while (rs.next()) {

        String serie = rs.getString(1); // rs is the previously built resultSet
        String unit = rs.getString(2);
        Stribg country = rs.getString(3);
        BigDecimal value = rs.getBigDecimal(4);
        int year = rs.getInt(5);
        CountryFirstData data = new CountryFirstData(country, serie, unit));
        CountryFirstData oldData = identityMap.putIfAbsent(data, data);
        if (oldData != null) {
            data = oldData;
        }
        data.getDuo().add(new YearValueDuo(year, value));
    }
    long parsingEnd = System.nanoTime();

    System.out.println("Parsing Time = " + ((parsingEnd - parsingStart)/1_000_000_000L));

    return (SortedSet<CountryFi‌​rstData>) identityMap.keySet()‌​;
}

这取决于equals上现有的比较

这里的诀窍是 - 虽然你只需要一个Set - ,但需要一个身份图来获取旧的相等值&#39;(Set.add只返回一个布尔值)。

因为这仍然很慢:

确保ResultSet已按SQL ORDER BY serie, unit, country排序。 (如果已经排序,那将解释先前解决方案的缓慢:树形图,它变成线性列表。)

public List<CountryFirstData> sortCountryFirst() throws SQLException {

    long parsingStart = System.nanoTime();

    List<CountryFirstData> identityMap = new ArrayList<>();
    CountryFirstData oldData = null;
    while (rs.next()) {
        String serie = rs.getString(1); // rs is the previously built resultSet
        String unit = rs.getString(2);
        Stribg country = rs.getString(3);
        BigDecimal value = rs.getBigDecimal(4);
        int year = rs.getInt(5);
        CountryFirstData data = new CountryFirstData(country, serie, unit));
        if (oldData == null || data.compareTo(oldData) != 0) {
            oldData = data;
            list.add(data);
        }
        oldData.getDuo().add(new YearValueDuo(year, value));
    }
    long parsingEnd = System.nanoTime();

    System.out.println("Parsing Time = " + ((parsingEnd - parsingStart)/1_000_000_000L));

    return list;
}

这使得数据库付出了艰辛的努力。什么是最快的,可以利用指数。