2

次のSQLのすべてのデータをマップに入れたいのですが(このSQLは何度も呼び出され、毎回dbに行くのではなく)、タイムスタンプに <= を実装する方法が不思議です

編集:

私はOracleを使用していますが、タグを更新したばかりですが、再コンパイルせずにクエリをキャッシュするJavaでPreparedStatementを使用していますが、プログラムにはテーブルからデータをキャッシュするキャッシュソリューションがありません。データベースにアクセスしてデータを取得するには往復で 2 ミリ秒かかりますが、HashMap からデータを取得するにはナノ秒かかります。このクエリは約 20,000 回実行されており、最初にすべてのデータをロードして Hashmap 内に配置したいと考えています。

編集の終わり。

SELECT ar   
FROM table1   
WHERE fk_col1 = ?   
AND timestamp_col <= ?   
ORDER BY date DESC 

私が行った方法は次のとおりです。しかし、わかりません。equals と hashCode の timestamp_col は正しいです。変更を提案していただけますか?

public class Table1Key
{
    private String fk_col1;
    private java.sql.Timestamp timestamp_col;
    //setters and getters here.
    //implementing hashCode and equals.
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
                + ((fk_col1 == null) ? 0 : fk_col1.hashCode());
        result = prime * result
                + ((timestamp_col == null) ? 0 : timestamp_col.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Table1Key other = (Table1Key) obj;
        if (fk_col1 == null) {
            if (other.fk_col1 != null)
                return false;
        } else if (!fk_col1.equals(other.fk_col1))
            return false;
        if (timestamp_col == null) {
            if (other.timestamp_col != null)
                return false;
        } else if (!timestamp_col.equals(other.timestamp_col))
            return false;
        return true;
    }
}

...

private Map<Table1Key, String> map = Functions.getHashMapInstance();

public class Functions {
...
  public static <K,V> HashMap<K,V> getHashMapInstance() {
      return new HashMap<K,V>();
  }
}

したがって、次のようにマップにデータを入力します。

private void populateMap() throws SQLException {
      try {
        ps = conn.prepareStatement(table1Sql);
        ps.setFetchSize(20000);
        ResultSet rs = ps.executeQuery();
        while(rs.next()) {
            Table1Key rdk = new Table1Key();
            String ar = rs.getString(1);
            rdk.setFk_col1(rs.getString(2));
            rdk.setTimestampCol(rs.getTimestamp(3));
            if(actualRateMap.get(rdk) == null) {
                actualRateMap.put(rdk, ar);
            }
        }
    } catch (SQLException e) {
        e.printStackTrace();
        throw e;
    } finally {
        ps.close();
    }
  }

// ここにキーを設定します。

Table1Key tk = new Table1Key();
tk.setFk_col1(col1);
tk.setTimestampCol(timestamp);
String ar = actualRateMap.get(tk);

//ここでの私の主な関心事は..これは、SQLにtimestamp_col = ?がある場合に機能しますが、timestamp_colがマップに存在するものよりも小さい場合はどうなりますか?

if(actualRate != null) {
    Logger.info("Actual Rate:"+actualRate);
}
4

2 に答える 2

2

HashMapあなたのケースでは仕事をしませんが、むしろTreeMapが役立ちます。

a): RangeMapソリューション

Guava RangeMapは、そのようなケースを処理するように設計されています。

//Initial RangeMap  
final RangeMap<java.sql.Timestamp, String> cache = TreeRangeMap.create();
...
String value = cache.get(thisTimestamp);
if(value == null){
     String queryFromDB = ...;//Query from DB
     cache.put(Range.atMost(thisTimestamp), queryFromDB);
     value = queryFromDB;
}

もちろん、「fk_coll」は問題です。そのため、ケースを処理するように定義できますMap<String/*fk_coll*/, RangeMap<java.sql.Timestamp, String>>

b): TreeMapソリューション

final TreeMap<java.sql.Timestamp, String> cache = new TreeMap<>();
...
//Get least key greater than or equal to the 'thisTimestamp' 
Map.Entry<java.sql.Timestamp, String> entry = cache.ceilingEntry(thisTimestamp);
if(entry == null){
   String queryFromDB = ...;//Query from DB
   cache.put(thisTimestamp, queryFromDB);
   value = queryFromDB;
} else {
   value = entry.getValue();
}

HashMap<String/*fk_coll*/, TreeMap<java.sql.Timestamp, String>>

「fk_coll」を処理します。

プラス:キャッシュの場合、エビクトは問題です。

于 2013-02-15T16:57:41.927 に答える
0

HashMap は要素の順序を指定しませんが、TreeMap は指定します。次のコードはテストしていませんが、動作するはずです。

TreeMap<Timestamp, String> map = new TreeMap<Timestamp, String>(new Comparator<Timestamp>() {
    public int compare(Timestamp t1, Timestamp t2) {
       // Inverse order is required for using tailMap() as <= operator
       return t2.compareTo(t1);
    }

    public boolean equals(Object o) {
       throw new UnsupportedOperationException("This operation has not been implemented!");
    }
});
// TODO: insert data to the map
// ...

// Get the first key that is <= timestamp (remember that map is using inverse order)
TreeMap<Timestamp, String> tailMap = map.tailMap(timestamp);
Timestamp firstKey = tailMap.firstKey();
if (firstKey != null) {
  // Get the value
  String value = tailMap.get(firstKey);
}
于 2013-02-15T17:20:53.767 に答える