Biblioteca cliente Java para comunicação com um servidor de banco de dados por meio de seus protocolos. A implementação atual suporta apenas a interface HTTP.
A biblioteca fornece sua própria API para enviar requisições a um servidor. Ela também oferece ferramentas para trabalhar com diferentes formatos de dados binários (RowBinary* & Native*).
A autenticação por token de acesso requer a configuração do token de acesso por meio da chamada A autenticação por certificado de cliente SSL requer a definição do nome de usuário, a habilitação da autenticação SSL, e a configuração de um certificado de cliente e uma chave de cliente por meio das chamadas
resultará no seguinte valor de O aplicativo pode definir seu próprio cabeçalho HTTP ⚠️ Quando as opções são definidas por meio do método Quando as opções são definidas por meio do método ParâmetrosParâmetrosParâmetrosParâmetrosParâmetrosParâmetrosParâmetrosParâmetrosMétodos de V2 Inserir dados no formato TSV.
Setup
- Maven Central (página do projeto na web): https://mvnrepository.com/artifact/com.clickhouse/client-v2
- Builds noturnas (link do repositório): https://central.sonatype.com/repository/maven-snapshots/
- Artifactory das compilações Nightly antigas (link do repositório): https://s01.oss.sonatype.org/content/repositories/snapshots/
- Maven
- Gradle (Kotlin)
- Gradle
Inicialização
O objeto Client é inicializado porcom.clickhouse.client.api.Client.Builder#build(). Cada cliente tem seu próprio contexto e nenhum objeto é compartilhado entre eles.
O Builder possui métodos de configuração para facilitar a configuração.Exemplo:showLineNumbers
Client é AutoCloseable e deve ser fechado quando não for mais necessário.Autenticação
A autenticação é configurada por cliente na fase de inicialização. Há três métodos de autenticação suportados: por senha, por token de acesso e por certificado de cliente SSL.A autenticação por senha requer a definição do nome de usuário e da senha por meio das chamadassetUsername(String) e setPassword(String):showLineNumbers
setAccessToken(String):showLineNumbers
setUsername(String), useSSLAuthentication(boolean), setClientCertificate(String) e setClientKey(String), respectivamente:showLineNumbers
A autenticação SSL pode ser difícil de diagnosticar em produção, porque muitos erros das bibliotecas SSL não fornecem informações suficientes. Por exemplo, se o certificado e a chave do cliente não corresponderem, o servidor encerrará a conexão imediatamente (no caso de HTTP, isso acontecerá na fase de estabelecimento da conexão, quando nenhuma requisição HTTP é enviada e, portanto, nenhuma resposta é retornada).Use ferramentas como openssl para verificar certificados e chaves:
- verificar a integridade da chave:
openssl rsa -in [key-file.key] -check -noout - verificar se o certificado do cliente tem um CN correspondente a um usuário:
- obter o CN de um certificado de usuário -
openssl x509 -noout -subject -in [user.cert] - verificar se o mesmo valor está definido no banco de dados
select name, auth_type, auth_params from system.users where auth_type = 'ssl_certificate'(a consulta retornaráauth_paramscom algo como{"common_names":["some_user"]})
- obter o CN de um certificado de usuário -
Configuração
Todas as configurações são definidas por métodos de instância (também conhecidos como métodos de configuração) que deixam o escopo e o contexto de cada valor explícitos. Os principais parâmetros de configuração são definidos em um único escopo (cliente ou operação) e não se substituem entre si.A configuração é definida durante a criação do cliente. Consultecom.clickhouse.client.api.Client.Builder.Configuração do Cliente
- Conexão & Endpoints
- Autenticação
- Timeouts & retentativas
- Opções do socket
- Compressão
- SSL/Segurança
- Proxy
- HTTP & Cabeçalhos
- Configurações do servidor
- Fuso horário
- Avançado
Identificação do Cliente
Há dois campos em um log de consulta que identificam a aplicação que originou uma requisição:client_name e http_user_agent. O protocolo native TCP usa
client_name para identificar a aplicação. O protocolo HTTP usa http_user_agent para identificar a aplicação. O construtor de cliente possui o método setClientName para definir os valores corretos
para ambos os protocolos.
O campo http_user_agent é definido de acordo com o formato comum do header User-Agent: application-name[/version] [(operating-system; architecture; ...)].
Esse conjunto de valores é repetido para cada layer: aplicação, biblioteca cliente e biblioteca cliente HTTP. O que é definido pelo método setClientName aparece primeiro na lista.Por exemplo:showLineNumbers
http_user_agent:User-Agent para se identificar. Porém, a parte clickhouse-java-v2/0.9.6-SNAPSHOT será adicionada ao final do cabeçalho.Identificação de Operação
O log de consultas tem mais dois campos,query_id e log_comment, que podem ser usados para identificar uma operação e adicionar mais informações ao log de consultas.query_id é um identificador único de uma operação. Ele pode ser definido pela aplicação ao chamar o método setQueryId da classe QuerySettings.showLineNumbers
log_comment é um comentário que pode ser adicionado ao log de consultas. Ele pode ser definido pela aplicação ao chamar o método logComment da classe QuerySettings.showLineNumbers
Configurações do Servidor
As configurações do lado do servidor podem ser definidas no nível do cliente uma única vez durante a criação (consulte o métodoserverSetting do Builder) e no nível da operação (consulte serverSetting na classe de configurações de operação).showLineNumbers
setOption (seja na classe Client.Builder ou na classe de configurações de operação), o nome das server settings deve ser prefixado com clickhouse_setting_. O método com.clickhouse.client.api.ClientConfigProperties#serverSetting() pode ser útil nesse caso.HTTP Header Personalizado
HTTP headers personalizados podem ser definidos para todas as operações (nível de cliente) ou para uma única (nível de operação).showLineNumbers
setOption (seja no Client.Builder ou na classe de configurações da operação), o nome do cabeçalho personalizado deve ser prefixado com http_header_. O método com.clickhouse.client.api.ClientConfigProperties#httpHeader() pode ser útil nesse caso.Definições Comuns
ClickHouseFormat
Enum dos formatos compatíveis. Inclui todos os formatos suportados pelo ClickHouse.raw- o usuário deve transcodificar os dados brutosfull- o cliente pode transcodificar os dados por conta própria e aceita um fluxo de dados brutos-- operação não suportada pelo ClickHouse para este formato
API de Insert
insert(String tableName, InputStream data, ClickHouseFormat format)
Aceita dados como umInputStream de bytes no formato especificado. Espera-se que data esteja codificado no format.AssinaturastableName - nome da tabela de destino.data - um fluxo de entrada de dados codificados.format - um formato no qual os dados são codificados.settings - configurações da requisição.Valor de retornoFuture do tipo InsertResponse - resultado da operação e informações adicionais como métricas do lado do servidor.ExemplosshowLineNumbers
insert(String tableName, List<?> data, InsertSettings settings)
Envia uma requisição de escrita ao banco de dados. A lista de objetos é convertida em um formato eficiente e então enviada ao servidor. A classe dos itens da lista deve ser registrada previamente usando o métodoregister(Class, TableSchema).AssinaturastableName - nome da tabela de destino.data - objetos DTO (Data Transfer Object) de coleção.settings - configurações da requisição.Valor de retornoFuture do tipo InsertResponse - o resultado da operação e informações adicionais, como métricas do lado do servidor.ExemplosshowLineNumbers
InsertSettings
Opções de configuração para operações de inserção.Métodos de configuraçãoInsertResponse
Objeto de resposta que contém o resultado da operação de inserção. Ele só estará disponível se o cliente receber uma resposta do servidor.Esse objeto deve ser fechado assim que possível para liberar a conexão, porque ela não pode ser reutilizada até que todos os dados da resposta anterior sejam lidos por completo.
API de Consulta
query(String sqlQuery)
EnviasqlQuery sem modificações. O formato da resposta é definido pelas configurações da consulta. QueryResponse manterá uma referência ao stream de resposta que deve ser consumido por um leitor para o formato suportado.AssinaturassqlQuery - uma única instrução SQL. A consulta é enviada sem modificações para um servidor.settings - configurações da requisição.Valor de retornoFuturo do tipo QueryResponse — um conjunto de dados de resultado e informações adicionais, como métricas do lado do servidor. O objeto Response deve ser fechado após o consumo do conjunto de dados.Exemplosquery(String sqlQuery, Map<String, Object> queryParams, QuerySettings settings)
EnviasqlQuery sem modificações. Além disso, enviará parâmetros de consulta para que o servidor possa compilar a expressão SQL.AssinaturassqlQuery - expressão SQL com placeholders {}.queryParams - map de variáveis para completar a expressão SQL no servidor.settings - configurações da requisição.Valor de retornoFuture do tipo QueryResponse - um conjunto de dados de resultado e informações adicionais como métricas do lado do servidor. O objeto Response deve ser fechado após o consumo do conjunto de dados.ExemplosshowLineNumbers
queryAll(String sqlQuery)
Consulta dados no formatoRowBinaryWithNamesAndTypes. Retorna o resultado como uma coleção. O desempenho de leitura é o mesmo que com o leitor, mas é necessária mais memória para armazenar o conjunto de dados completo.AssinaturassqlQuery - expressão SQL para consultar dados em um servidor.Valor de retornoConjunto de dados completo representado por uma lista de objetos GenericRecord que fornecem acesso no estilo de linha aos dados resultantes.ExemplosshowLineNumbers
QuerySettings
Opções de configuração para operações de consulta.Métodos de configuraçãoQueryResponse
Objeto de resposta que contém o resultado da execução da consulta. Ele só estará disponível se o cliente tiver recebido uma resposta do servidor.Este objeto deve ser fechado o quanto antes para liberar a conexão, pois ela não pode ser reutilizada até que todos os dados da resposta anterior sejam lidos por completo.
Exemplos
- O código de exemplo está disponível no repositório
- Referência de implementação do Spring Service
API Comum
getTableSchema(String table)
Busca o esquema da tabelatable.Assinaturastable - nome da tabela para a qual os dados de esquema devem ser buscados.database - banco de dados onde a tabela de destino está definida.Valor de retornoRetorna um objeto TableSchema com a lista de colunas da tabela.getTableSchemaFromQuery(String sql)
Obtém o esquema a partir de uma instrução SQL.Assinaturassql - Instrução SQL “SELECT” cujo esquema deve ser retornado.Valor de retornoRetorna um objeto TableSchema com colunas correspondentes à expressão sql.TableSchema
register(Class<?> clazz, TableSchema schema)
Compila a camada de serialização e desserialização para a classe Java usar na gravação/leitura de dados com oschema. O método criará um serializador e um desserializador para o par getter/setter e a coluna correspondente.
A correspondência da coluna é feita extraindo seu nome do nome de um método. Por exemplo, getFirstName corresponderá à coluna first_name ou firstname.Assinaturasclazz - Classe que representa o POJO usado para leitura/gravação de dados.schema - Esquema de dados a ser usado para correspondência com propriedades POJO.ExemplosshowLineNumbers
Exemplos de uso
O código completo dos exemplos está armazenado no repositório na pasta ‘example`:- client-v2 - coleção principal de exemplos.
- demo-service - exemplo de uso do cliente em uma aplicação Spring Boot.
- demo-kotlin-service - exemplo de como usar o cliente em um aplicativo Ktor (Kotlin).
Lendo Dados
Existem duas maneiras comuns de ler dados:- método
query()que retorna um objetoQueryResponsede baixo nível, que contém umInputStreamcom os dados. Geralmente combinado comClickHouseBinaryFormatReaderpara leituras em streaming, mas pode ser usado com qualquer outra implementação personalizada de leitor.QueryResponsetambém fornece acesso aos metadados do conjunto de resultados e às métricas. - método
queryAll()e uso deGenericRecordpara acesso prático às linhas. Nesse caso, todo o conjunto de resultados é carregado na memória. - método
queryRecords()que retornacom.clickhouse.client.api.query.Records— um iterador de objetosGenericRecord. Esse método usa uma abordagem de streaming (nenhum dado é carregado na memória) e utilizaGenericRecordpara acessar os dados.
Lendo Arrays
Métodos deClickHouseBinaryFormatReadergetList(...)- lê qualquerArray(...)comoList<T>. Boa opção padrão para leituras tipadas flexíveis. Suporta arrays aninhados.getByteArray(...),getShortArray(...),getIntArray(...),getLongArray(...),getFloatArray(...),getDoubleArray(...),getBooleanArray(...)- mais indicados para arrays unidimensionais de valores compatíveis com tipos primitivos.getStringArray(...)- paraArray(String)(e valores deenumrepresentados por nomes).getObjectArray(...)- opção genérica para qualquer tipo de elemento deArray(...), incluindo arrays aninhados. Use-a para ler arrays com valores Nullable e arrays aninhados.
GenericRecordgetList(...)- lê qualquerArray(...)comoList<T>. Boa opção padrão para leituras tipadas flexíveis. Suporta arrays aninhados.getByteArray(...),getShortArray(...),getIntArray(...),getLongArray(...),getFloatArray(...),getDoubleArray(...),getBooleanArray(...)- mais indicados para arrays unidimensionais de valores compatíveis com tipos primitivos.getStringArray(...)- paraArray(String)(e valores deenumrepresentados por nomes).getObjectArray(...)- opção genérica para qualquer tipo de elemento deArray(...), incluindo arrays aninhados. Use-a para ler arrays com valores Nullable e arrays aninhados.
Guia de Migração
O cliente antigo (V1) usavacom.clickhouse.client.ClickHouseClient#builder como ponto de partida. O novo cliente (V2) utiliza um padrão semelhante com com.clickhouse.client.api.Client.Builder. As principais
diferenças são:- nenhum carregador de serviço é usado para recuperar a implementação. A
com.clickhouse.client.api.Clienté uma classe de fachada para todos os tipos de implementação que vierem a existir. - menos fontes de configuração: uma é fornecida ao builder e a outra fica nas configurações da operação (
QuerySettings,InsertSettings). A versão anterior tinha configuração por nó e, em alguns casos, carregava variáveis de ambiente.
Correspondência de Parâmetros de Configuração
Existem 3 classes enum relacionadas à configuração na V1:com.clickhouse.client.config.ClickHouseDefaults- parâmetros de configuração que devem ser definidos na maioria dos casos de uso, comoUSERePASSWORD.com.clickhouse.client.config.ClickHouseClientOption- parâmetros de configuração específicos do cliente, comoHEALTH_CHECK_INTERVAL.com.clickhouse.client.http.config.ClickHouseHttpOption- parâmetros de configuração específicos da interface HTTP, comoRECEIVE_QUERY_PROGRESS.
com.clickhouse.client.config.ClickHouseDefaults#ASYNC e
com.clickhouse.client.config.ClickHouseClientOption#ASYNC?). O novo cliente V2 utiliza com.clickhouse.client.api.Client.Builder como dicionário único de todas as opções de configuração possíveis do cliente. Em com.clickhouse.client.api.ClientConfigProperties estão listados todos os nomes de parâmetros de configuração.A tabela abaixo mostra quais opções antigas são compatíveis com o novo cliente e seus novos significados.Legenda: ✔ = compatível, ✗ = não compatível- Conexão & autenticação
- SSL & Segurança
- Opções do socket
- Compressão
- Proxy
- Timeouts & retentativas
- Fuso horário
- Buffers & Desempenho
- Threads & Assincronia
- HTTP & Cabeçalhos
- Formato & Consulta
- Descoberta de nós & balanceamento de carga
- Diversos
Diferenças Gerais
- O Client V2 usa menos classes proprietárias para aumentar a portabilidade. Por exemplo, o V2 funciona com qualquer implementação de
java.io.InputStreampara gravar dados em um servidor. - A configuração
asyncdo Client V2 vem comooffpor padrão. Isso significa que não há threads extras e que a aplicação tem mais controle sobre o cliente. Essa configuração deve permaneceroffna maioria dos casos de uso. Ao habilitarasync, uma thread separada será criada para cada solicitação. Isso só faz sentido ao usar um executor controlado pela aplicação (vejacom.clickhouse.client.api.Client.Builder#setSharedOperationExecutor)
Gravação de dados
- use qualquer implementação de
java.io.InputStream. A versão V1com.clickhouse.data.ClickHouseInputStreamé compatível, mas NÃO é recomendada. - Uma vez detectado o fim do fluxo de entrada, ele é tratado adequadamente. Antes disso, o fluxo de saída de uma requisição deve ser fechado.
- há apenas um método para chamar. Não é necessário criar um objeto de requisição adicional.
- o stream do corpo da requisição é fechado automaticamente quando todos os dados são copiados.
- há uma nova API de baixo nível disponível
com.clickhouse.client.api.Client#insert(java.lang.String, java.util.List<java.lang.String>, com.clickhouse.client.api.DataStreamWriter, com.clickhouse.data.ClickHouseFormat, com.clickhouse.client.api.insert.InsertSettings).com.clickhouse.client.api.DataStreamWriterfoi projetado para implementar uma lógica personalizada de gravação de dados. Por exemplo, lendo dados de uma fila.
Lendo Dados
- Os dados são lidos no formato
RowBinaryWithNamesAndTypespor padrão. No momento, apenas esse formato é compatível quando o binding de dados é necessário. - Os dados podem ser lidos como uma coleção de registros usando o método
List<GenericRecord> com.clickhouse.client.api.Client#queryAll(java.lang.String). Ele lê os dados para a memória e libera a conexão. Não é necessário nenhum tratamento adicional.GenericRecordfornece acesso aos dados e implementa algumas conversões.