Google Cloud Bigtable

SGBD´s, ou sistemas gerenciadores de bancos de dados, são utilizados há muito tempo. Soluções famosas como Oracle, Postgres, MySQL estão entre as mais populares. Uma característica que as três soluções mencionadas compartilham é o suporte primário ao modelo relacional para armazenamento de dados. Hoje em dia, existem diversas opções de bancos de dados que podem ser muito mais performáticos do que bancos de dados relacionais para necessidades especificas, essas soluções são englobadas em uma categoria denominada NoSQL (Not Only SQL). Dentro do universo NoSQL temos bancos orientados a chave-valor, colunares, documentos, séries temporais, entre outras opções.

Onde o Bigtable se enquadra?

O Bigtable é um banco NoSQL voltado para o armazenamento de dados no esquema chave-valor. A solução é totalmente gerenciada pela Google e suporta bilhões de registros, milhares de colunas e Peta bytes de dados. Suas características o tornam uma solução interessante para aplicações que armazenam grandes volumes de dados, e demandam alto volume de consultas e escritas com baixa latência.

Um case de uso interessante onde podemos considerar o Bigtable é o armazenamento de dados financeiros baseados em séries temporais. Necessidade essa muito comum em soluções que atendem o mercado acionário.

Demonstração prática

Não vou entrar nos detalhes de como criar uma conta na GCP, mas basta acessar a página https://cloud.google.com/ e seguir o passo a passo. Ao criar uma conta na GCP, são disponibilizados $300 em créditos para serem utilizados em até 90 dias. Muito mais do que o necessário para essa demonstração.

Uma vez logado no console do GCP, vamos primeiramente criar um projeto dedicado para a demonstração, depois é só apagar o projeto inteiro a fim de evitar cobranças.

Após criar o projeto, vamos acessar o painel de controle do Bigtable. No menu lateral, do lado esquerdo, basta clicar em Bigtable na seção Bancos de Dados.

Na sequência, crie uma instância do Bigtable:

Detalhe para o preço em destaque. Então, cuidado para não deixar a instância no ar sem necessidade =):

 

Agora, basta preencher os campos e clicar em “create”.

A instância criada foi definida com apenas um node. Essa propriedade afeta a performance da instância e o custo. Ela pode ser atualizada a qualquer momento. Para o nosso case, 1 node é mais do que o suficiente.

Caso amanhã precisemos aprimorar a performance da nossa instância, basta voltar aqui e incluir mais nodes.

Ao clicar no nome da instância, teremos acesso ao painel geral que oferece uma série de estatísticas sobre ela:

No menu lateral, acesse a opção “Table”. Conforme a imagem, ainda não temos nenhuma tabela:

Nosso case de estudo

Vamos ilustrar um cenário onde se faz necessário a criação de uma aplicação que irá expor uma API, para consulta a dados de uma série temporal com valores históricos de um conjunto de ativos financeiros da bolsa de valores brasileira.

Trabalhando no design da tabela

A estrutura de dados necessária é a seguinte:

  Família A Família B Família C
Rowkey Ativo Data Alta Baixa Abertura Fechamento Volume Fechamento Ajustado
                 

Pontos importantes:

 

1- Rowkey: É o identificador único de um registro. A definição da nossa chave deve ser bem planejada, pois influenciará muito na performance de nossa instância do Bigtable.

Algo a ser evitado é a criação de uma rowkey baseada simplesmente em números sequenciais ou datas. Isto porque o Bigtable irá ordenar os registros através dessa coluna, e dependendo do schema/volume de dados e das características das consultas que serão realizadas, nossa aplicação pode ser prejudicada.

Para o nosso cenário, uma proposta interessante de chave é compor a mesma pelo nome do ativo e data do registro.

nomeAtivo#yyyymmdd

Exemplo:

BBDC4#20200121

Dessa forma, o mecanismo de ordenação do Bigtable vai organizar os registros por ativo e data, o que, no nosso caso, vai aprimorar a performance das consultas.

2- Famílias: Conforme mencionado. o Bigtable suporta milhares de colunas, e, a fim de colaborar com a organização das colunas, é possível agrupá-las em famílias. No caso, agrupamos algumas colunas apenas para fins de demonstração.

Para o nosso case, vamos trabalhar com uma base de dados disponibilizada aqui. Trata-se de um arquivo csv com o histórico de preços de alguns ativos da bolsa de valores brasileira. O histórico é do ano de 2020.

Abaixo, temos uma amostragem dos dados:

Ativo Data Alta Baixa Abertura Fechamento Volume Fechamento Ajustado
BBDC4 02/01/2020 34,09999847 32,90908813 33,20909119 34,09999847 20687260 33,07200241
BBDC4 03/01/2020 34,54545212 33,52727127 33,54545212 34,09999847 33057090 33,08722305
BBDC4 06/01/2020 33,89090729 33,12727356 33,81818008 33,49090958 27830990 32,49622345
BBDC4 07/01/2020 33,59999847 32,72727203 33,40908813 32,90908813 16343030 31,9316864
BBDC4 08/01/2020 33,20000076 32,23636246 33,06363678 32,40000153 23393480 31,43770599
BBDC4 09/01/2020 32,62727356 31,56363678 32,52727127 31,88181877 25437390 30,93491936

Usando o CBT para criar a tabela, inserir e consultar dados

Agora que já conhecemos o nosso conjunto de dados, vamos começar a interagir com o BigTable. Ele dispõe de uma ferramenta padrão para interação, trata-se do CBT ou “Cloud Bigtable Command Line Tool”. Vamos fazer uso do CBT através do Cloud Shell. Por padrão, o Cloud Shell já vem com o CBT instalado, caso estivéssemos acessando a partir de nossa máquina seria necessário instalá-lo.

O usuário que estou usando possui privilégios administrativos, caso contrário eu precisaria atribuir privilégios para interagir com o Bigtable.

Uma vez no Cloud Shell, vamos precisar criar um arquivo denominado “.cbtrc”. Defina nesses arquivos duas variáveis:

project = [id-do-seu-projeto] (ID e não o nome)

instance = [nome-de-sua-instância-bigtable]

Esse arquivo é necessário para que não precisemos informar essas constantes em todos os comandos. Feito isso, podemos testar o CBT através do comando abaixo:

cbt version

Será aberta uma janela solicitando autorização para acessar APIs internas. Basta dar OK. A saída do comando será algo semelhante ao que segue abaixo:

Agora, vamos criar a nossa tabela com o comando abaixo:

cbt createtable historicoAtivos

Podemos validar que nossa tabela foi criada através do seguinte comando:

cbt ls

Crie as Column Families da nossa tabela:

 

cbt createfamily historicoAtivos familiaA
cbt createfamily historicoAtivos familiaB
cbt createfamily historicoAtivos familiaC

Podemos validar as Column Families criadas através do comando abaixo:

cbt ls historicoAtivos

Agora, insira um registro na tabela:

cbt set historicoAtivos BBDC4#04/01/2020 familiaA:ativo=BBDC4 familiaA:data=02/01/2020 familiaB:alta=34.09999847 familiaB:baixa=32.90908813 familiaB:abertura=33.20909119 familiaB:fechamento=34.09999847 familiaC:volume=20687260 familiaC:fechamentoAjustado=33.07200241

Podemos consultar o registro inserido com o seguinte comando:

cbt read historicoAtivos

 Podemos apagar os registros da tabela com este comando:

cbt deleteallrows historicoAtivos

Após isto, insira 8 registros através dos comandos do arquivo localizado aqui. Abaixo seguem as rowkeys dos registros em questão:

Após inseri-los, podemos consultar a quantidade de registros disponíveis através destee comando:

cbt count historicoAtivos

Agora, selecione apenas os registros da MGLU3:

cbt read historicoAtivos prefix=MGLU3

E aqui vamos selecionar os registros da MGLU3 de 01/01/2019 até 02/01/2020:

cbt read historicoAtivos start=MGLU3#20190101 end=MGLU3#20200102

Apenas um registro atende ao filtro (o valor informado para o atributo END não é considerado):

Interagindo com o BigTable através de bibliotecas

O CBT é uma ferramenta interessante para fins de testes e consultas rápidas. Porém, pensando em soluções de software, precisaremos fazer uso de bibliotecas para fins de integração. O BigTable oferece as seguintes opções:

C++ C# Java Go HBase (Java) Node.js PHP Python Ruby

Vamos realizar alguns testes através da opção nativa para Java:

<dependency>
    <groupId>com.google.cloud</groupId>
    <artifactId>google-cloud-bigtable</artifactId>
    <version>1.5.0</version>
</dependency>

Consulte um registro pela rowkey:

private void getRecordsByKey( String key) {

    try {
        Row row = this.dataClient.readRow(Constantes.BT_TABLE_ID, key);
        printRecord(row);

    } catch (Exception e) {
        System.out.println(“Error getRecordsByKey”);
        e.printStackTrace();
    }
}

 

E consulte registros por faixa de valores:

private  void getRecordsByKeyRange(String start, String end) {
    try {
        Query query = Query.create(Constantes.BT_TABLE_ID).range(start, end);
        ServerStream<Row> rows = this.dataClient.readRows(query);

        rows.forEach(r->printRecord(r));

    } catch (Exception e) {
        System.out.println(“Error getRecordsByKeyRange”);
        e.printStackTrace();
    }
}

 

O projeto com a implementação dos métodos acima e de alguns métodos extras pode ser encontrado aqui.

Resumo

Nesse artigo conhecemos um pouco do Bigtable, seus conceitos e a importância de uma modelagem correta. Verificamos alguns exercícios práticos, para interação com o banco de dados através do CBT e também através da biblioteca Java.

Referências

[Google Bigtable]

https://cloud.google.com/bigtable

[Treinamentos Google Bigtable]

https://cloud.google.com/bigtable/docs#training-and-tutorials

[Hello world com java]

https://cloud.google.com/bigtable/docs/samples-java-hello-world

[Github do projeto apresentado]

https://github.com/eumagnun/artigo-bigtable.git