2015-02-27 2 views
5

Ich muss eine der Tabellen in Cassandra mit Datastax Java-Treiber abfragen. Unten ist der Code, den ich, der gut arbeitet haben -Wie vorbereitete Anweisung effizient mit Datenstabe Java-Treiber in Cassandra verwenden?

public class TestCassandra { 

     private Session session = null; 
     private Cluster cluster = null; 

     private static class ConnectionHolder { 
      static final TestCassandra connection = new TestCassandra(); 
     } 

     public static TestCassandra getInstance() { 
      return ConnectionHolder.connection; 
     } 

     private TestCassandra() { 
      Builder builder = Cluster.builder(); 
      builder.addContactPoints("127.0.0.1"); 

      PoolingOptions opts = new PoolingOptions(); 
      opts.setCoreConnectionsPerHost(HostDistance.LOCAL, opts.getCoreConnectionsPerHost(HostDistance.LOCAL)); 

      cluster = builder.withRetryPolicy(DowngradingConsistencyRetryPolicy.INSTANCE).withPoolingOptions(opts) 
        .withLoadBalancingPolicy(new TokenAwarePolicy(new DCAwareRoundRobinPolicy("DC2"))) 
        .withReconnectionPolicy(new ConstantReconnectionPolicy(100L)) 
        .build(); 
      session = cluster.connect(); 
     } 

    private Set<String> getRandomUsers() { 
     Set<String> userList = new HashSet<String>(); 

     for (int table = 0; table < 14; table++) { 
      String sql = "select * from testkeyspace.test_table_" + table + ";"; 

      try { 
       SimpleStatement query = new SimpleStatement(sql); 
       query.setConsistencyLevel(ConsistencyLevel.QUORUM); 
       ResultSet res = session.execute(query); 

       Iterator<Row> rows = res.iterator(); 
       while (rows.hasNext()) { 
        Row r = rows.next(); 

        String user_id = r.getString("user_id"); 
        userList.add(user_id); 
       } 
      } catch (Exception e) { 
       System.out.println("error= " + ExceptionUtils.getStackTrace(e)); 
      } 
     } 

     return userList; 
    } 
} 

ich so in meinem Haupt oben Klasse bin mit -

TestCassandra.getInstance().getRandomUsers(); 

irgendeine Weise gibt es ich PreparedStatement in getRandomUsers effizienter nutzen können? Ich denke, ich muss sicherstellen, dass ich PreparedStatement nur einmal erstelle, anstatt es mehrmals zu erstellen. Was ist das beste Design dafür in meiner aktuellen Architektur und wie kann ich es verwenden?

Antwort

11

Sie können einen Cache (dies ist ein ziemlich einfaches Beispiel für eine Idee) der Anweisungen erstellen, die Sie benötigen. Beginnen wir mit der Erstellung der Klasse, die als Cache verwendet wird.

private class StatementCache { 
    Map<String, PreparedStatement> statementCache = new HashMap<>(); 
    public BoundStatement getStatement(String cql) { 
     PreparedStatement ps = statementCache.get(cql); 
     // no statement cached, create one and cache it now. 
     if (ps == null) { 
      ps = session.prepare(cql); 
      statementCache.put(cql, ps); 
     } 
     return ps.bind(); 
    } 
} 

dann eine Instanz zu Ihrem Singleton hinzu:

public class TestCassandra { 
    private Session session = null; 
    private Cluster cluster = null; 
    private StatementCache psCache = new StatementCache(); 
    // rest of class... 

Und schließlich den Cache von Ihrer Funktion:

private Set<String> getRandomUsers(PreparedStatement ps) { 
// lots of code.  
     try { 
      SimpleStatement query = new SimpleStatement(sql); 
      query.setConsistencyLevel(ConsistencyLevel.QUORUM); 
      // abstract the handling of the cache to it's own class. 
      // this will need some work to make sure it's thread safe 
      // as currently it's not. 
      ResultSet res = session.execute(psCache.getStatement(sql)); 
+0

Das ist genial. Ich habe jetzt verstanden, was wir tun müssen, im Grunde müssen wir eine Singleton-Thread-sichere Klasse erstellen, in der wir alle neuen Anweisungen in einem Cache auffüllen und dann diese Anweisungen vom Getter verwenden müssen. Recht? – john

+0

@david Eigentlich hätte ich einen Cache pro n Threads (Sie müssen trainieren, wenn die Karte zu teuer wird, was bedeutet, dass ein neuer gemeinsamer Cache benötigt wird) Versuchen Sie so etwas wie 1 Cache pro 5 Threads. Möglicherweise sollte sogar jeder Thread seinen eigenen PS-Cache haben (basierend darauf, wie viele Anweisungen darin enthalten sind, je mehr Anweisungen, desto weniger Caches benötigen Sie). –

+0

Ich habe deinen letzten Kommentar nicht verstanden, Cache pro n Threads? Wie können wir das machen? – john

Verwandte Themen