Como conseguimos reduzir nosso cluster de Redshift e aumentar a performance?

Compartilhe

Compartilhar no facebook
Compartilhar no google
Compartilhar no twitter
Compartilhar no linkedin

Usamos o Redshift aqui na Movile há mais de 4 anos e, em meados de Fevereiro do ano passado, decidimos fazer uma reestruturação total de nosso cluster.

Queríamos reduzir em 60% nosso cluster, porém manter um volume de dados semelhante e também uma performance igual ou superior à que tínhamos. 

O Redshift era usado, na época, como a fonte de todas as análises que fazíamos, ou seja, perder performance não era algo que poderia acontecer.

Ousado, não?

A minha ideia aqui é consolidar, em um único artigo, quais foram os principais conceitos e técnicas que aplicamos para atingir nosso objetivo. E ah, sim, nós o alcançamos ! 

Fazendo um review da Arquitetura do Redshift

Captura de Tela 2018-04-24 às 17.57.39

É muito importante conhecer como o Redshift funciona internamente para conseguir fazer as otimizações. O Redshift possui dois tipos de nodes, o Leader Node e o Compute Node.

O primeiro é responsável por receber e coordenar as queries e armazenar os metadados, enquanto o segundo é o que de fato trabalha na execução da sua consulta.

 

 

Captura de Tela 2018-04-24 às 17.59.20

Além dos dois tipos de nodes, o Redshift também possui dois tipos de hardware. Um é otimizado para processamento, o Dense Computing (DC), e o Dense Storage (DS) é otimizado para o armazenamento de dados.

Cada node é dividido internamente em slices, que por sua vez  possui memória e CPU dedicados. Essa configuração também é variável de acordo com o tipo do node e do cluster.

No DC, temos 2 slices em um servidor large e 32 em um x-large, enquanto que no DS temos apenas 2 slices em um x-large.

Cada slice processa paralelamente uma parte do workload, também conhecido como Massive Parallel Processing (MPP).

Por isso, é muito importante você já saber para qual finalidade está criando o seu cluster. Aqui nós utilizamos o DC porque nossa prioridade é aproveitar toda a performance para consolidar nossos dados.

  • E como nós atingimos nosso objetivo?

    Agora explicarei conceitos de performance e tuning que utilizamos para atingir nosso objetivo. 

    Antes de iniciarmos esta task-force, foi muito importante parar e entender como o Redshift funciona internamente, como os dados são distribuídos e ordenados, quais são as melhores práticas e rotinas de manutenção  indicadas.

    Conhecendo os nossos dados e sabendo quais buscas e análises são as mais frequentes, conseguimos reduzir o tamanho das tabelas, em média, 60% e ter uma performance superior de, em média, 40%.

    Começarei falando de distribuição dos dados, depois sobre ordenação e por fim compressão.

    Distribuição dos dados

    O Redshift replica os dados entre seus nodes de acordo com algumas regras, porém você precisa tomar um certo cuidado ao definir essas regras, pois elas estão diretamente ligadas à performance do seu cluster

    O objetivo aqui é minimizar a movimentação de dados e distribuí-los uniformemente para termos ganhos efetivos no processamento paralelo. Existem 3 tipos de distribuição no Redshift:

    • Distribution Style All: Aqui a tabela é replicada em todo node, sempre no primeiro slice. É indicado para tabelas de lookup que sempre são usadas em joins;
    • Distribution Style Even: Neste estilo os dados são distribuídos entre os nodes utilizando o round-robin. Não existe uma regra na distribuição dos dados, é de certa maneira aleatória;
    • Distribution Key: Neste estilo utiliza-se uma coluna para distribuir os dados. É importante levar alguns pontos para defini-la: alta cardinalidade, frequentemente usada em joins e também com os dados uniformes em tamanho.

 

Captura de Tela 2018-04-24 às 18.02.37.png

Ordenação dos dados

Sem dúvida, se você ordenar sua tabela pela(s) coluna(s) que mais usa, você terá um ganho muito grande na performance. 

Existe um conceito chamado Zone-Map, que é algo que o Redshift usa quando seu dado está ordenado de maneira correta dentro dos slices. 

Ele lê o metadado de cada um e verifica o range de max e min dos dados, além de fazer a checagem para ver se precisa ler o dado de fato. Isso te dá um ganho muito grande em performance. Existem três tipos de ordenação:

  • Single: este é o tipo usado quando você define apenas uma coluna. Você deve usar uma coluna que é comumente usada em cláusulas where. É muito importante isso, porque definindo de maneira correta, o Redshift vai conseguir usar, de verdade, as zone-maps..Captura de Tela 2018-04-24 às 18.04.11
  • Compound: aqui você consegue definir até 400 colunas. Fazendo um paralelo com o banco relacional, pense em um índice composto, ou seja, a coluna à esquerda sempre tem precedência em relação às da direita. É assim também que funciona esse tipo de ordenação. É muito bom quando você utiliza group by e/ou order by com as colunas

Captura de Tela 2018-04-24 às 18.05.06

 

Interleaved: você consegue definir até 8 colunas neste estilo. É indicado para quando você tem várias colunas com a mesma importância/frequência de uso. O custo de manutenção deste estilo é um pouco maior do que o compound, mas você acaba tendo ganhos maiores quanto maior for sua tabela.

 

  • Captura de Tela 2018-04-24 às 18.07.28

    Compressão dos dados

    Por ser um banco colunar, a compressão de dados pode ser muito melhor do que um banco relacional. Isso porque existem tipos específicos de compressão para cada tipo de dado.

    Fazendo a compressão dos mesmos você tem ganhos de espaço, de memória e de I/O. Ano passado a AWS lançou o tipo zstd de compressão, que deu um salto muito grande na liberação de espaço. 

    É bem importante olhar os tipos de cada coluna e quais tipos de compressão são indicados para ela. Caso você não tenha certeza de qual tipo de compressão usar, você pode criar a tabela sem nenhuma e após ela ter 1MM de registros, rodar o comando ANALYZE COMPRESSION, onde o próprio Redshift irá sugerir um tipo de compressão para cada coluna.

Entendendo bem quais serão suas chaves de ordenação, estilos e chaves de distribuição você já conseguirá um ganho muito alto no desempenho. Aliando isso à compressão correta dos dados, você não ganhará somente em desempenho, mas também reduzirá em muito o I/O.

Melhores práticas

Conforme os dados são inseridos nas tabelas, ela acaba perdendo a ordenação e distribuição, suas estatísticas vão ficando defasadas e a performance acaba caindo. 

Para controlar isso é sempre importante ter rotinas de VACUUM agendadas nessas tabelas, elas garantirão que os dados sejam rearranjados e distribuídos/ordenados de maneira correta. 

É muito importante também rodar rotinas de ANALYZE, elas garantem que as estatísticas da tabela sempre permaneçam atualizadas. Assim, é possível sempre ter um ótimo plano de execução da query.

Captura de Tela 2018-04-24 às 18.10.12.png

Captura de Tela 2018-04-24 às 18.11.24Evite colunas grandes: O indicado é sempre mantê-las com o menor tamanho possível, isso porque colunas grandes são sinônimos de desperdício de memória, já que a alocação do buffer é baseada no tamanho dela. 

Além disso, desta maneira você acaba armazenando menos registros na memória, podendo recorrer ao disco, o que acaba se tornando um gargalo.

Workload management (WLM)

outro

 

 

É onde você controla as filas de execução, definindo shares do hardware para cada uma delas, bem como o tempo de execução. 

Você pode definir até 8 filas de execução. Só tenha cuidado porque a porcentagem de hardware que você define para cada uma é dedicada, ou seja, imagine que você definiu 4 filas, cada uma com 25%. Se apenas uma fila estiver com queries em execução, ela só  poderá/conseguirá usar os 25% dela, mesmo que 75% esteja “disponível”. 

Uma recomendação é definir 4 filas com 20% cada para query e outras duas filas com 10% cada para processos de ETL.

Uso de temp tables

Captura de Tela 2018-04-24 às 18.14.12

O recurso de criação de tabelas temporárias é algo amplamente usado e de fato muito bom! Só que deve-se tomar um cuidado ao criá-las. 

Quando ela é criada como “CREATE TEMP TABLE … AS SELECT …” o Redshift utiliza por default o estilo Even de distribuição, ou seja, se você utilizar uma coluna para filtro, todos os slices serão lidos. 

Além disso, ele cria a tabela sem nenhuma compressão. Por isso, é recomendado criar primeiro a estrutura da tabela temporária “CREATE TEMP TABLE table-name (field1 datatype encode, ….) DISTKEY(field) SORTKEY(field)”, desta maneira você consegue não somente definir as chaves e estilo de distribuição, como também as chaves de ordenação. Por default o Redshift aplica o encoding zstd, mas você também consegue definir.

Conclusão

Tentei colocar aqui tudo o que vimos e percebemos que é essencial para conseguir, não só fazer um tuning em seu Redshift, mas também mantê-lo com esta performance constante.

Aliando as boas práticas, o tuning e o conhecimento da sua base, sem dúvida é possível ter ganhos significativos de performance.

Espero que essa troca de aprendizado ajude quem estiver passando por situações similares às quais passamos aqui.

Fontes:

Guilherme Brunhole

Guilherme Brunhole

Guilherme Brunhole trabalha com dados há mais de 4 anos e hoje é o responsável por essa área no Rapiddo Vision, um marketplace da Movile. Além disso é um dos fundadores da UAUBox, um clube de assinaturas de produtos de beleza que utiliza data science para encontrar os produtos ideais para cada perfil.

Deixe um comentário

%d blogueiros gostam disto: