Apache IoTDB Series Tutorial-4: Client Interface

After talking about grammar and deployment operation and maintenance for a long time, the actual use still has to fall into the code. Today, I will introduce the client interface.

The body text is 3516 words, and the estimated reading time is 5 minutes.

The current client and server communication uses the cross-language RPC framework Thirft. In theory, all languages ​​that Thrift can generate can support. But the code generated by Thrift directly is not very friendly to database users, so we packaged our various client interfaces based on the generated code, which is more user-friendly. Next, introduce the various client interfaces.

JDBC interface

JDBC is a standard interface for relational databases, and it is also the most familiar interface. So we provided this interface from the beginning.

As with standard JDBC, you need to load database driver classes, establish connections, establish Statements, and execute statements through Statements. For non-queries, you can perform batch execution to reduce the number of network transmissions. Here is a simple example,

public static void main(String[] args) throws ClassNotFoundException, SQLException {
    Class.forName("org.apache.iotdb.jdbc.IoTDBDriver");
    try (Connection connection = DriverManager
        .getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
        Statement statement = connection.createStatement()) {
      // 创建存储组
      statement.execute("SET STORAGE GROUP TO root.sg1");
      // 创建时间序列
      statement.execute("CREATE TIMESERIES root.sg1.d1.s1 WITH DATATYPE=INT64, ENCODING=RLE, COMPRESSOR=SNAPPY");
      statement.execute("CREATE TIMESERIES root.sg1.d1.s2 WITH DATATYPE=INT64, ENCODING=RLE, COMPRESSOR=SNAPPY");
      statement.execute("CREATE TIMESERIES root.sg1.d1.s3 WITH DATATYPE=INT64, ENCODING=RLE, COMPRESSOR=SNAPPY");
      // 在客户端积累一批更新语句
      for (int i = 0; i <= 100; i++) {
        statement.addBatch("insert into root.sg1.d1(timestamp, s1, s2, s3) values("+ i + "," + 1 + "," + 1 + "," + 1 + ")"); 
      }
      // 执行
      statement.executeBatch();
      statement.clearBatch();
      // 查询
      ResultSet resultSet = statement.executeQuery("select * from root where time <= 10");
      // 打印结果集
      ResultSetMetaData metaData = resultSet.getMetaData();
      int columnCount = metaData.getColumnCount();
      while (resultSet.next()) {
        for (int i = 1; i < columnCount; i++) {
          System.out.print(resultSet.getString(i));
          System.out.print(" ");
        }
        System.out.println();
      }
    }
  }

The complete sample code location:

https://github.com/apache/incubator-iotdb/blob/master/example/jdbc/src/main/java/org/apache/iotdb/JDBCExample.java

Java native interface Session

For data writing, SQL parsing takes up 70% of the time. So we provide a native NoSQL interface (Session), which is more efficient than JDBC.

insertRecord(String deviceId, long time, List<String> measurements,
      List<TSDataType> types, List<Object> values)

This interface corresponds to an insert statement, which can write the value of multiple measuring points with one time stamp for one device at a time. The value type needs to be consistent with the registered type. If it has not been registered, this type will be automatically registered.

insertRecord(String deviceId, long time, List<String> measurements,
      List<String> values)

In some scenarios, the client cannot get the specific data type, and this String parameter interface can be used at this time. If the sequence is registered in advance, the server will parse the value of these Strings according to the registered type. If it is not registered, it will infer the type according to the value format and register it.

insertTablet(Tablet tablet, boolean sorted)

A tablet is the value of multiple time stamps and multiple measuring points of a device. It should be noted here that each measurement point needs to have a value at each time stamp, and there can be no empty ones. sorted indicates whether the timestamp is incremented. If it can be guaranteed to be incremented, it can be set to true, otherwise we will sort it again.

If you only calculate the execution time, this interface is the most efficient, because it uses primitive arrays to avoid boxing. However, this interface has high requirements on the format of the data. If the data collection is not aligned, it is forced to be converted into this interface, and the time-consuming conversion needs to be counted.

In addition, there are two types: insertTablets and insertRecords, which are actually the batch forms of the above interfaces.

The query result set of the Session is SessionDataSet. The hasNext and next methods provided by this structure convert each row of data into a RowRecord structure. If the client needs to do other transformations, this structure is redundant. At this time, you can get an iterator through SessionDataSet.iterator(). This iterator accesses data in the same way as JDBC ResultSet. It takes data directly from the byte array, which is more efficient than RowRecord.

The complete sample code location:

https://github.com/apache/incubator-iotdb/blob/master/example/session/src/main/java/org/apache/iotdb/SessionExample.java

Connection pool SessionPool

Since the birth of the native interface, many users have migrated from JDBC to the original interface. We have also expanded the capabilities of the native interface and increased the connection pool of Session (Dong Ge's dedication). The interface of the connection pool is basically the same as that of the Session, but the connection pool can be used by multiple threads and can shield problems such as abnormal connection.

The only thing to note when using the connection pool is that the result set obtained by the query needs to be returned to the connection pool (call the closeResultSet method of the connection pool) after use, otherwise the connection will be occupied and a new connection will be reported as a timeout.

SessionDataSetWrapper wrapper = null;
try {
  wrapper = pool.executeQueryStatement("select * from root.sg1.d1");
  while (wrapper.hasNext()) {
    System.out.println(wrapper.next());
  }
} catch (IoTDBConnectionException | StatementExecutionException e) {
  e.printStackTrace();
} finally {
  // remember to close data set finally!
  pool.closeResultSet(wrapper);
}

The complete sample code location:

https://github.com/apache/incubator-iotdb/blob/master/example/session/src/main/java/org/apache/iotdb/SessionPoolExample.java

Python interface

In addition to the JAVA interface, we also wrapped the Python interface, which was added after version 0.9. Location at 

https://github.com/apache/incubator-iotdb/blob/master/client-py

to sum up

Today I mainly introduced the JDBC interface, the JAVA native interface Session and the connection pool. There are some precautions inside, such as when using SessionPool to do a query, you need to manually close the result set (I am very impressed with this, I have stepped on the pit for a few days).

Guess you like

Origin blog.csdn.net/qiaojialin/article/details/106893861