Apache Druid supports two query languages: Druid SQL and native queries. This document describes using the JDBC driver for SQL queries.
You can make Druid SQL queries using the Avatica JDBC driver. We recommend using Avatica JDBC driver version 1.23.0 or later.
Connection string
The basic connection string format:
jdbc:avatica:remote:url=http://localhost:8888/druid/v2/sql/avatica/;transparent_reconnection=true
For protobuf protocol instead of JSON:
jdbc:avatica:remote:url=http://localhost:8888/druid/v2/sql/avatica-protobuf/;transparent_reconnection=true;serialization=protobuf
The /druid/v2/sql/avatica/ endpoint on the Router, which provides connection stickiness.
Maintains connection if the Broker pool changes membership or a Broker restarts.
Set to protobuf when using the protobuf endpoint for better performance with large result sets.
Connection stickiness
Druid’s JDBC server does not share connection state between Brokers. You must either:
- Connect to a specific Broker, or
- Use a load balancer with sticky sessions
- Use the Druid Router process (provides stickiness automatically)
The non-JDBC JSON over HTTP API is stateless and doesn’t require stickiness.
Java code example
import java.sql.*;
import java.util.Properties;
public class DruidJDBCExample {
public static void main(String[] args) throws SQLException {
// Connect to /druid/v2/sql/avatica/ on your Router
String url = "jdbc:avatica:remote:url=http://localhost:8888/druid/v2/sql/avatica/;transparent_reconnection=true";
// Set connection context parameters
Properties connectionProperties = new Properties();
connectionProperties.setProperty("sqlTimeZone", "Etc/UTC");
// For basic authentication
connectionProperties.setProperty("user", "admin");
connectionProperties.setProperty("password", "password1");
try (Connection connection = DriverManager.getConnection(url, connectionProperties)) {
try (
final Statement statement = connection.createStatement();
final ResultSet resultSet = statement.executeQuery("SELECT * FROM wikipedia LIMIT 10")
) {
while (resultSet.next()) {
// Process result set
String timestamp = resultSet.getString("__time");
String user = resultSet.getString("user");
System.out.println(timestamp + " - " + user);
}
}
}
}
}
Dynamic parameters
You can use parameterized queries with PreparedStatement:
PreparedStatement statement = connection.prepareStatement(
"SELECT COUNT(*) AS cnt FROM druid.foo WHERE dim1 = ? OR dim1 = ?"
);
statement.setString(1, "abc");
statement.setString(2, "def");
final ResultSet resultSet = statement.executeQuery();
Array parameters
Using STRING_TO_ARRAY:
PreparedStatement statement = connection.prepareStatement(
"SELECT l1 FROM numfoo WHERE SCALAR_IN_ARRAY(l1, STRING_TO_ARRAY(CAST(? as varchar),','))"
);
List<Integer> li = ImmutableList.of(0, 7);
String sqlArg = Joiner.on(",").join(li);
statement.setString(1, sqlArg);
statement.executeQuery();
Using native arrays:
PreparedStatement statement = connection.prepareStatement(
"SELECT l1 FROM numfoo WHERE SCALAR_IN_ARRAY(l1, ?)"
);
Iterable<Object> list = ImmutableList.of(0, 7);
ArrayFactoryImpl arrayFactoryImpl = new ArrayFactoryImpl(TimeZone.getDefault());
AvaticaType type = ColumnMetaData.scalar(Types.INTEGER, SqlType.INTEGER.name(), Rep.INTEGER);
Array array = arrayFactoryImpl.createArray(type, list);
statement.setArray(1, array);
statement.executeQuery();
Table metadata is available through standard JDBC methods or by querying INFORMATION_SCHEMA:
// Using JDBC metadata
DatabaseMetaData metaData = connection.getMetaData();
ResultSet tables = metaData.getTables(null, "druid", "wikipedia", null);
// Using INFORMATION_SCHEMA
String query = "SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS " +
"WHERE TABLE_NAME = 'wikipedia' AND TABLE_SCHEMA = 'druid'";
ResultSet rs = statement.executeQuery(query);
while (rs.next()) {
String columnName = rs.getString("COLUMN_NAME");
String dataType = rs.getString("DATA_TYPE");
System.out.println(columnName + ": " + dataType);
}
Prerequisites
Before using the JDBC driver:
Context parameters
Set SQL query context parameters using the Properties object. Available parameters include:
sqlTimeZone: Set query timezone (e.g., “America/Los_Angeles”)
useCache: Enable/disable result caching
populateCache: Control cache population
useApproximateCountDistinct: Use approximate algorithms
useApproximateTopN: Use approximate TopN
See the SQL query context documentation for all available parameters.
Protobuf endpoint
The protobuf endpoint offers reduced overhead and better performance for large result sets:
String url = "jdbc:avatica:remote:url=http://localhost:8888/druid/v2/sql/avatica-protobuf/;transparent_reconnection=true;serialization=protobuf";
The protobuf endpoint also works with the official Golang Avatica driver.