Desenvolver aplicativos com o GoogleSQL para Bigtable
Você pode usar o GoogleSQL para Bigtable para executar consultas dos seus aplicativos e descarregar funções de computação no Bigtable. Isso reduz a necessidade de processamento do lado do cliente. O GoogleSQL é uma linguagem de consulta estruturada compatível com ANSI implementada para o Bigtable e outros Google Cloud serviços. Para mais informações sobre outros usos do GoogleSQL para Bigtable, consulte a Visão geral do GoogleSQL para Bigtable.
Antes de começar
Verifique se você tem o seguinte:
- Uma instância e uma tabela do Bigtable.
- A biblioteca de cliente do Bigtable para sua linguagem. Para mais informações sobre como instalar e usar bibliotecas de cliente para Bigtable, consulte Bibliotecas de cliente do Bigtable.
- Autenticação configurada usando o Application Default Credentials (ADC). Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.
Exemplo de cenário
Os exemplos neste guia usam uma tabela de amostra weather-data que pode ser acessada
na instância de teste sem custo financeiro no
Google Cloud console. Suponha que sua tabela armazene informações de diferentes estações meteorológicas identificadas por um station_id. Cada estação registra a temperatura na escala Fahrenheit em uma coluna chamada temp_f. Em vez de calcular a temperatura no aplicativo, você pode usar uma consulta SQL para converter essas temperaturas para a escala Celsius diretamente no Bigtable antes de enviar os resultados de volta ao aplicativo. Para
mais informações sobre como consultar a tabela de dados meteorológicos, consulte Consultar dados de amostra.
Práticas recomendadas
Para otimizar o desempenho e o uso de recursos, considere as seguintes práticas recomendadas ao desenvolver aplicativos:
- Reutilizar o cliente:crie um único
BigtableDataClientpara seu aplicativo. O cliente processa o gerenciamento de canais gRPC e foi projetado para alta simultaneidade. Recomendamos que você crie esse cliente uma vez após a inicialização do aplicativo e o reutilize para cada consulta. - Usar consultas parametrizadas:use
PreparedStatementpara separar a lógica de consulta dos valores de dados. Isso permite que o Bigtable armazene em cache o plano de execução e evita a injeção de SQL. - Reutilizar instruções preparadas:chame
PreparedStatementapenas uma vez por string SQL. Armazene e reutilize a instrução em várias solicitações.
Criar o cliente do Bigtable
Para processar a conexão entre o aplicativo e o Bigtable, crie um BigtableDataClient. O exemplo a seguir mostra como compartilhar uma única instância de cliente no aplicativo para gerenciar conexões com eficiência:
BigtableDataSettings settings = BigtableDataSettings.newBuilder()
.setProject(PROJECT_ID)
.setInstance(INSTANCE_ID)
.build();
// The client is thread-safe and should be reused.
try (BigtableDataClient dataClient = BigtableDataClient.create(settings)) {
System.out.println("Connected to: " + INSTANCE_ID);
}
Preparar a consulta
Em vez de colocar os dados diretamente em uma string SQL, recomendamos o uso de consultas parametrizadas. No GoogleSQL para Bigtable, as consultas parametrizadas são equivalentes a uma instrução preparada. Isso permite separar a lógica de consulta dos valores de dados.
O exemplo a seguir mostra como definir sua consulta do GoogleSQL usando marcadores de posição de parâmetro, como @sid. Em seguida, crie um PreparedStatement especificando a string SQL e os tipos de cada parâmetro para que a consulta possa ser executada mais rapidamente na próxima vez:
Map<String, SqlType<?>> paramTypes = new HashMap<>();
paramTypes.put("sid", SqlType.string());
String sql = "SELECT " +
"ROUND((CAST(CAST(weather['temp_f'] AS STRING) AS INT64) - 32) * 5 / 9, 2) AS temp_celsius " +
"FROM " + TABLE_NAME + " WHERE station_id = @sid LIMIT 1";
// Create and reuse the PreparedStatement.
PreparedStatement preparedStatement = dataClient.prepareStatement(sql, paramTypes);
Executar a consulta
Forneça valores de parâmetro e execute a consulta. O exemplo a seguir mostra como usar o PreparedStatement para vincular valores aos parâmetros e criar um BoundStatement. Em seguida, ele executa a consulta e faz um loop nos resultados para imprimir o ResultSet, que é a temperatura em graus Celsius:
BoundStatement boundStatement = preparedStatement.bind()
.setStringParam("sid", stationId)
.build();
try (ResultSet resultSet = dataClient.executeQuery(boundStatement)) {
while (resultSet.next()) {
System.out.println("Temp: " + resultSet.getDouble("temp_celsius"));
}
}
Verificar a estrutura de dados
Ao desenvolver ou explorar o SQL, recomendamos que você explore os metadados associados à tabela para entender a estrutura de dados. Como o Bigtable tem um esquema flexível, se você usar consultas SELECT *, os resultados da consulta poderão mudar com base nos dados. Portanto, recomendamos que você não use consultas SELECT * em aplicativos de produção.
O exemplo a seguir analisa os metadados do conjunto de resultados (como os nomes e tipos de coluna) e os envia de volta ao cliente de forma independente dos dados. Isso permite que você receba as informações da coluna primeiro e crie a estrutura de dados necessária para processar os dados no aplicativo.
ResultSetMetadata metadata = resultSet.getMetadata();
System.out.print("Columns: ");
metadata.getColumnsList().forEach(col -> System.out.print(col.getName() + " "));
System.out.println();
Trabalhar com grupos de colunas
O Bigtable armazena dados em grupos de colunas. O GoogleSQL
retorna essas famílias como listas de nomes e valores conhecidos como
mapas de qualificadores e valores de coluna. Ao ler um grupo de colunas, o Bigtable retorna o tipo SqlType.Map. Ao ler um grupo de colunas de uma tabela com histórico, como SELECT column FROM my_table(with_history=>true), o Bigtable retorna um tipo SqlType.historicalMap(), que é um mapa de qualificadores de coluna e uma matriz de carimbos de data/hora e valores de célula. Para mais exemplos de SqlType tipos, consulte
SqlType.
O exemplo a seguir mostra como, em vez de receber uma coluna por vez, você pode receber um grupo inteiro de colunas de uma só vez. O código armazena o grupo de colunas em um mapa para que você possa fazer um loop em todos os nomes e valores:
Map<String, SqlType<?>> paramTypes = new HashMap<>();
paramTypes.put("keyPrefix", SqlType.bytes());
String sql = String.format("SELECT weather FROM %s WHERE STARTS_WITH(_key, @keyPrefix)", TABLE_NAME);
PreparedStatement preparedStatement = dataClient.prepareStatement(sql, paramTypes);
BoundStatement boundStatement = preparedStatement.bind()
.setBytesParam("keyPrefix", ByteString.copyFromUtf8(key))
.build();
try (ResultSet resultSet = dataClient.executeQuery(boundStatement)) {
while (resultSet.next()) {
SqlType.Map<ByteString, ByteString> mapType = SqlType.mapOf(SqlType.bytes(), SqlType.bytes());
Map<ByteString, ByteString> weatherValues = resultSet.getMap("weather", mapType);
for (Map.Entry<ByteString, ByteString> entry : weatherValues.entrySet()) {
System.out.printf("%s = %s\n",
entry.getKey().toStringUtf8(),
entry.getValue().toStringUtf8());
}
}
}
A seguir
- Consulte a documentação de referência do GoogleSQL para Bigtable .
- Saiba como escrever SQL com a assistência do Gemini.