2016-08-17 11 views
-2

前のクエリーから巨大なResultSetを解析する必要があり、何かが思いつきましたが、遅すぎます。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つの異なる値を含んでいます。考慮する最初のトリオは、country,serieおよびunitで構成されています。最初にそのようなトリオ(elseケース)を取得するときは、新しいCountryFirstDataを作成し、resultSet行の残ったデュオ年/値を、作成されたオブジェクトのYearValueDuoリストフィールドに追加する必要があります。

トリオcountryserieunitが既にlistif場合)に存在し、私はそれを取得し、そのYearValueDuoリストにデュオ年/値を追加する必要があります。

したがって、結果セットrsの長さは4000行で、解析(ソート除外)全体は2分かかります。私はこれが唯一の4k行のためにあまりにも多いように感じる。ソートはまだ高速です(1秒未満です)。

CountryFirstDataの場合はArrayListを選択しましたが、後でそのリスト全体をファイル内にその順序で書き込みます(これは本当に速いです)。

あなたは私にいくつか改善を提案できますか?

+2

各行に '' list.indexOf(新しいCountryFirstData(国、セリ、ユニット)) ''を実行します。 '' CountryFirstData.equals''の複雑さによっては、 '' list''が3999個のエントリを持つときにはかなり時間がかかるかもしれません。 '' indexOf''メソッドが各行にかかる時間を測定しようとします。 – f1sh

+0

@ f1shするでしょう。指定された 'CountryFirstData'がすでにリストに存在するかどうかをテストするより良い方法は見つけられませんでした。 – Fitz

+0

(リストで)オブジェクトの1つのインスタンスを比較し、もう一方を追加すると醜いようです。 –

答えて

1

Aリスト、実際にはSet(double doubles)、その後はソートされます。実装クラスを返し、その型を使用するためのさらなる使用を強制し、実装の変更を防ぎます。

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()‌​; 
} 

これは既に対等にを比較し、既存に依存しています。

ここでは、Setが必要なだけですが、古い等価値を取得するためにIDマップが必要です(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; 
} 

これは、データベースにハードワークを残し:(つまり、線形リストとなり、ツリーマップすでにソートされた場合は、その前溶液中の遅さを説明するだろう。)。最も速く、インデックスを利用することができます。

+0

'return list.keySet();'は実際には 'return identityMap.keySet();'を意味すると思いますか?ティ、私は今しようとします。 – Fitz

+0

私に5秒の勝ちました。何もありません、ありがとう! – Fitz

+0

非常に高速なソリューションを追加しましたが、SQLを変更する必要があります。 –