# Broker GRPC API

Apart from HTTP based query endpoint, Pinot also supports gRPC endpoint in broker.

## Enable GRPC query entrypoint in broker

Add gRPC port config in pinot broker to enable the [`BrokerGrpcServer`](https://github.com/apache/pinot/blob/master/pinot-broker/src/main/java/org/apache/pinot/broker/grpc/BrokerGrpcServer.java):

```editorconfig
pinot.broker.grpc.port=8010
```

if you want to enable TLS, then use below configs:

```editorconfig
pinot.broker.grpc.tls.enabled=true
pinot.broker.grpc.tls.port=8020

// Server side TLS is used. The client does not present a certificate.
// The server only verifies the client’s connection via its own certificate and doesn’t validate the client’s identity via TLS.
// Common in public APIs, where only the server needs to be trusted.
pinot.broker.grpctls.client.auth.enabled=false

// Config TLS keystore and truststore
pinot.broker.grpctls.keystore.path=/home/pinot/tls-store/keystore-internal.jks
pinot.broker.grpctls.keystore.password=changeit
pinot.broker.grpctls.keystore.type=JKS
pinot.broker.grpctls.truststore.path=/home/pinot/tls-store/truststore.jks
pinot.broker.grpctls.truststore.password=changeit
pinot.broker.grpctls.truststore.type=JKS
```

## Broker GRPC Clients

Below are the examples of usage for `pinot-java-client` and `pinot-jdbc-client` .

### Java Grpc Client

The main difference of the usage here is that `ConnectionFactory` will return a **`GrpcConnection`** instead of **`Connection`**.

{% hint style="warning" %}
If you want to use ARROW as the encoding type, you must start Java with

&#x20;`--add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED`&#x20;

(See <https://arrow.apache.org/docs/java/install.html>)
{% endhint %}

Below is a sample code to use the java client: **GrpcConnection**:

```java
package org.apache.pinot.client.examples;

import java.io.IOException;
import java.util.Properties;
import org.apache.pinot.client.ConnectionFactory;
import org.apache.pinot.client.ResultSetGroup;
import org.apache.pinot.client.grpc.GrpcConnection;


public class PinotBrokerGrpcClientExample {

  private PinotBrokerGrpcClientExample() {
  }
  
  public static void main(String[] args)
      throws IOException {
    Properties properties = new Properties();
    properties.put("encoding", "JSON");
    properties.put("compression", "ZSTD");
    properties.put("blockRowSize", "10000");
    GrpcConnection grpcConnection = ConnectionFactory.fromControllerGrpc(properties, "localhost:9000");
    // GrpcConnection grpcConnection = ConnectionFactory.fromZookeeperGrpc(properties, "localhost:2123/QuickStartCluster");
    // GrpcConnection grpcConnection = ConnectionFactory.fromHostListGrpc(properties, List.of("localhost:8010"));
    ResultSetGroup resultSetGroup = grpcConnection.execute("SELECT * FROM airlineStats limit 1000");
    for (int i = 0; i < resultSetGroup.getResultSetCount(); i++) {
      org.apache.pinot.client.ResultSet resultSet = resultSetGroup.getResultSet(i);
      for (int rowId = 0; rowId < resultSet.getRowCount(); rowId++) {
        System.out.print("Row Id: " + rowId + "\t");
        for (int colId = 0; colId < resultSet.getColumnCount(); colId++) {
          System.out.print(resultSet.getString(rowId, colId) + "\t");
        }
        System.out.println();
      }
    }
    grpcConnection.close();
  }
}
```

### JDBC Grpc Client

The main usage difference here is scheme is changed to `pinotgrpc`.

{% hint style="warning" %}
If you want to use ARROW as the encoding type, you must start Java with

&#x20;`--add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED`&#x20;

(See <https://arrow.apache.org/docs/java/install.html>)
{% endhint %}

Below is a sample code to use JDBC driver.

```java
package org.apache.pinot.client.examples;

import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;


public class PinotBrokerGrpcJdbcClientExample {

  private PinotBrokerGrpcJdbcClientExample() {
  }

  public static void main(String[] args)
      throws IOException {
    try (Connection connection = DriverManager.getConnection("jdbc:pinotgrpc://localhost:9000?blockRowSize=10000&encoding=JSON&compression=ZSTD");
        Statement statement = connection.createStatement();
        ResultSet resultSet = statement.executeQuery("SELECT * FROM airlineStats limit 1000")) {
      // Print results
      ResultSetMetaData metaData = resultSet.getMetaData();
      int columnCount = metaData.getColumnCount();
      while (resultSet.next()) {
        System.out.print("Row Id: " + resultSet.getRow() + "\t");
        for (int i = 1; i <= columnCount; i++) {
          System.out.print(metaData.getColumnName(i) + ": " + resultSet.getString(i) + "\t");
        }
        System.out.println();
      }
    } catch (SQLException e) {
      e.printStackTrace();
    }
  }
}
```

## Client Configurations

&#x20;Below are the parameters to set per connection basis:

1. **blockRowSize**: the number of rows per block that grpc response will return, **default** is **10000**.
2. **compression**: the compression algorithm over the wire, **default** is **ZSTD**, other options:&#x20;
   1. LZ4\_FAST: fast than LZ4\_HIGH but not as high compression rate
   2. LZ4\_HIGH
   3. **ZSTD (Default)**
   4. DEFLATE
   5. GZIP
   6. SNAPPY
   7. PASS\_THROUGH/NONE: no compression, fast but could be large data transfer over the wire.
3. **encoding**: how to do serialization and deserialization for ResultTable transport between BrokerGrpcServer and Grpc Client, **default** is **JSON**, other options:
   1. **JSON(Default)**
   2. ARROW

## Benchmark

We did a simple benchmark of query:&#x20;

```
SELECT * FROM airlineStats limit 1000
```

&#x20;Will compress **97k (9.2MB)** rows with block size **10K**.

### Compression

<table><thead><tr><th>CompressionType</th><th>Compression Ratio</th><th>Response Latency(ms)</th><th>Latency Ratio</th><th data-hidden></th></tr></thead><tbody><tr><td>LZ4_FAST</td><td><mark style="color:yellow;">42.19%</mark></td><td><mark style="color:green;">477.6</mark></td><td><mark style="color:green;">103.02%</mark></td><td></td></tr><tr><td>LZ4_HIGH</td><td><mark style="color:green;">30.04%</mark></td><td><mark style="color:yellow;">977.0</mark></td><td><mark style="color:red;">210.74%</mark></td><td></td></tr><tr><td>ZSTD</td><td><mark style="color:green;">26.10%</mark></td><td><mark style="color:green;">485.4</mark></td><td><mark style="color:green;">104.70%</mark></td><td></td></tr><tr><td>DEFLATE</td><td><mark style="color:green;">25.64%</mark></td><td><mark style="color:yellow;">810.0</mark></td><td><mark style="color:yellow;">174.72%</mark></td><td></td></tr><tr><td>GZIP</td><td><mark style="color:green;">25.64%</mark></td><td><mark style="color:yellow;">811.8</mark></td><td><mark style="color:yellow;">175.11%</mark></td><td></td></tr><tr><td>SNAPPY</td><td><mark style="color:yellow;">42.56%</mark></td><td><mark style="color:green;">461.2</mark></td><td><mark style="color:green;">99.48%</mark></td><td></td></tr><tr><td>NONE</td><td><mark style="color:red;">100%</mark></td><td><mark style="color:green;">463.6</mark></td><td><mark style="color:green;">100%</mark></td><td></td></tr></tbody></table>

### Block Size

We also tried for ZSTD the same data set with different block size:

| BlockRowSize | Compression Ratio                         | Avg Latency(ms)                          |
| ------------ | ----------------------------------------- | ---------------------------------------- |
| 100          | <mark style="color:yellow;">30.48%</mark> | <mark style="color:yellow;">539.6</mark> |
| 1000         | <mark style="color:green;">27.56%</mark>  | <mark style="color:green;">478.3</mark>  |
| 10000        | <mark style="color:green;">26.10%</mark>  | <mark style="color:green;">485.4</mark>  |
| 100000       | <mark style="color:green;">25.73%</mark>  | <mark style="color:yellow;">561.2</mark> |

### Encoding

Tested with ZSTD compression for the same query but different encoding and block size:

<table><thead><tr><th>BlockRowSize</th><th width="114.22998046875">Encoding</th><th width="123.03466796875">Compression</th><th width="150.7039794921875">Avg Latency(ms)</th><th width="98.7171630859375">Bytes</th><th width="160.693603515625">Compression Ratio</th></tr></thead><tbody><tr><td>1000</td><td>JSON</td><td>ZSTD</td><td><mark style="color:yellow;">473</mark></td><td><mark style="color:green;">2559246</mark></td><td><mark style="color:green;">27.56%</mark></td></tr><tr><td>10000</td><td>JSON</td><td>ZSTD</td><td><mark style="color:yellow;">473</mark></td><td><mark style="color:green;">2424082</mark></td><td><mark style="color:green;">26.10%</mark></td></tr><tr><td>100000</td><td>JSON</td><td>ZSTD</td><td><mark style="color:red;">594</mark></td><td><mark style="color:green;">2389717</mark></td><td><mark style="color:green;">25.73%</mark></td></tr><tr><td>1000</td><td>ARROW</td><td>ZSTD</td><td><mark style="color:green;">372</mark></td><td><mark style="color:yellow;">3054993</mark></td><td><mark style="color:yellow;">32.90%</mark></td></tr><tr><td>10000</td><td>ARROW</td><td>ZSTD</td><td><mark style="color:green;">367</mark></td><td><mark style="color:green;">2705245</mark></td><td><mark style="color:green;">29.13%</mark></td></tr><tr><td>100000</td><td>ARROW</td><td>ZSTD</td><td><mark style="color:yellow;">447</mark></td><td><mark style="color:yellow;">2809744</mark></td><td><mark style="color:yellow;">30.26%</mark></td></tr></tbody></table>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.pinot.apache.org/release-1.4.0/for-users/api/broker-grpc-api.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
