TabPy para trabalhar com dados no ClickHouse do Tableau

Construir comunicações entre marcas e pessoas é o que fazemos na Dentsu Aegis Network todos os dias, e a análise de dados é parte integrante deste trabalho. Em alguns casos, esse processo não requer ciência de dados (embora tenhamos uma), então usamos a plataforma Tableau BI. Seu principal objetivo é oferecer a nossos funcionários e clientes uma interface conveniente para o consumo de dados sem escrever scripts, consultas SQL, etc.

Neste artigo, descreveremos como conseguimos resolver o problema da interação do Tableau com o ClickHouse .

Declaração geral do problema


Enfrentamos um desafio clássico. Nós temos pessoas. Eles amam frutas. Algumas pessoas gostam de uma fruta, outras gostam de todas as frutas, e o resto pode amar qualquer combinação de frutas.
imagem
Portanto, é necessário permitir que o usuário no painel construído no Tableau selecione arbitrariamente várias frutas e veja quantas pessoas amam pelo menos uma fruta do conjunto. É claro que não tínhamos frutas, mas as pessoas eram reais, apenas nas "frutas" é mais fácil entender o problema.

A quantidade de dados no nosso caso é bastante grande. Havia 13 mil “frutas” diferentes. A "fruta" mais popular tinha quase 34 milhões de fãs. Em média, 450 mil pessoas amam cada "fruta". Total de amantes de frutas - 282 milhões.

Primeira solução na testa


Aconteceu que os dados para esta tarefa tínhamos no PostgreSQL (PG) e no ClickHouse (CH). No PG havia uma tabela de referência sobre “frutas”, na CH - uma tabela grande com uma estrutura: o identificador da “fruta” e o identificador da pessoa que ama essa “fruta”. Não há conector nativo para CH no Tableau, e eu ainda não queria transferir os dados para algum lugar, porque isso exigiria uma reformulação séria do sistema existente.

Tentamos conectar o Tableau ao CH usando o driver ODBC e ver o que acontece.

  • Nem todos os drivers ODBC são igualmente úteis. Precisamos de uma certa versão na qual a parte necessária da funcionalidade funcione, mas não há garantia de que o restante funcione se você precisar dela de repente.
  • Não foi possível extrair todos os dados no extrato do Tableau, pois são 13.000 * 450.000 = 5.850.000.000 registros.

Em seguida, decidimos usar a amostragem dentro da consulta no banco de dados CH, ou seja, para estimar o número de amantes da combinação selecionada de “frutas” não em todas as pessoas, mas em uma amostra de cinco por cento para diminuir o extrato. Além disso, imediatamente fizemos uma busca de junção interna do CH com um diretório PG "fruit" para obter os nomes "fruit". Ajudou - nosso extrato foi capaz de ser gerado em 5 horas.

Precisávamos atualizar os dados no painel uma vez por dia, portanto, 5 horas de atualização da extração parecem boas - atualizaremos à noite. Mas, no futuro, precisaríamos de capacidades adicionais: deveria haver mais “frutos”; portanto, o número e o tamanho de grupos de pessoas cuja interseção que precisávamos calcular também deveria aumentar. Portanto, uma longa atualização do extrato não é de todo nossa opção.

Além disso, houve outro problema devido à amostragem. Aconteceu que em diferentes partes do painel os números, que supostamente deveriam coincidir, eram diferentes em nosso país. Isso ocorreu devido ao fato de que em um lugar contamos o número de amantes de uma fruta com precisão, e em parte com uma combinação de frutas - imprecisa. Nem nós nem nossos usuários gostamos desse resultado.

Então decidimos não criar o extrato. Para evitar o carregamento de uma quantidade enorme de dados, dividimos os conjuntos de dados e usamos a conexão ao vivo para CH. Entre conjuntos de dados, uma conexão foi estabelecida usando a funcionalidade de relacionamento interna do Tableau Edit. A fonte de dados PG foi tornada primária e vinculada ao CH como secundária, usando o identificador "fruit" que estava nas duas tabelas.

Assim, conseguimos filtrar a fonte de dados secundária usando a primária (mistura de dados). Mas não tivemos êxito porque, depois de lançar o filtro de uma fonte de dados para outra, tivemos que usar a função de contar pessoas no subconjunto resultante (COUNTD), e a mistura de dados possui uma limitação que simplesmente não permite que isso seja feito. Essa função diretamente com essa conexão de dados não funciona em princípio.

Existe uma solução alternativa que ajuda a contornar essa limitação do Tableau, mas pode ser usada em conjuntos de dados relativamente pequenos, o que claramente não é o caso no nosso caso.

Depois disso, tentamos outra opção. Os conjuntos de dados ainda estavam divididos e usavam conexão ao vivo para CH. Aqui, um filtro de um conjunto de dados com uma descrição de "frutas" para um conjunto de dados com fãs de "frutas" foi lançado no Tableau usando a ação definida. Mas essa opção não se encaixou devido à interface do usuário inconveniente. Em vez do filtro familiar ao usuário, o usuário teria que olhar para a lista inteira e selecionar “frutas” via cntrl + click, enquanto a função aplicar estava ausente quando todos os valores selecionados são aplicados de uma só vez.

Como resultado, depois de todas as nossas tentativas, tivemos que voltar à opção com extração e amostragem, terrivelmente lenta e fornecendo apenas uma resposta aproximada.

imagem

Solução encontrada


Obviamente, não precisamos extrair todos os dados para a extração do Tableau. O usuário fica desconfortável ao ver todos os dados de uma só vez - o número de pessoas que amam todos os "frutos". Ele precisa de um conjunto de uma média de 10 "frutas". É uma pena que o Tableau não saiba como fazer isso.

Existem caras em nossa equipe que escrevem em Python. Portanto, em nossa pesquisa, decidimos avançar nessa direção e encontramos o TabPy .

O TabPy é um serviço da Web que permite obter o resultado da execução de scripts Python dentro dos custos no Tableau.

Como funciona:

  1. O Tableau interage com o TabPy e, por sua vez, com o Python, usando as chamadas Funções de Script. As funções de script contêm o próprio script Python, o tipo de dados necessário do resultado e os argumentos que passamos para essa função. No nosso caso, os argumentos foram identificadores de “frutos”, cujo número de amantes queríamos contar.
  2. O TabPy converte o texto das Funções de script recebidas em um script e o passa para o intérprete. A conexão com a base CH foi registrada por nós dentro do script.
  3. Em seguida, o TabPy retorna o resultado do script executado de volta ao Tableau.


imagem

Nas funções de script, os argumentos são sempre passados ​​como matrizes, o resultado também é retornado por uma matriz.

Nem tudo funcionou imediatamente. O principal que entendemos: escrever um script Python diretamente em um campo calculado no Tableau não é uma boa ideia. Por duas razões:

  1. Nas funções de script internas, às vezes é difícil usar a sintaxe familiar do Python. Por exemplo, várias cotações não são aceitas.
  2. Pensando no suporte futuro para o painel, percebemos que, se precisarmos alterar o script de alguma forma, sempre que precisarmos alterá-lo no próprio livro do Tableau. E essa claramente não é a melhor maneira, porque estamos fazendo o possível para evitar o suporte manual para painéis.

Portanto, usamos outra coisa - o TabPy Client .

O TabPy Client é uma biblioteca que permite publicar scripts Python no servidor TabPy e depois chamá-los no Tableau. Ao usá-lo, em vez de escrever um script no Tableau, chamamos o arquivo .py localizado no servidor TabPy usando os parâmetros especificados nele, passamos argumentos para ele e o executamos.

Essa abordagem resolveu nossos problemas usando o TabPy e o Tableau. O script é escrito e testado no ambiente de desenvolvimento familiar e armazenado separadamente do livro, que agora não requer suporte manual.

Para resolver nosso problema específico, tivemos que fazer o seguinte.
Inicialmente, tentamos resolvê-lo sem usar o TabPy Client. Nesse caso, um campo Cálculo do seguinte formulário foi criado no Tableau:
SE PRIMEIRO () == 0
ENTÃO
SCRIPT_INT ("
do cliente de importação clickhouse_driver
cliente = cliente (host = nome do host, banco de dados = nome do banco de dados, usuário = nome do usuário, senha = senha)

----- script_text -----

", SUM ([pessoas]), ATTR ([fruits_id]))
Fim
Funcionou, mas houve problemas que foram descritos acima. Quando descobrimos o TabPy Client, percebemos que, dividindo o campo Cálculo e o próprio script, obtemos um sistema mais conveniente e correto. É assim que o campo Cálculo e o arquivo .py com o script se parecem:
Campo de cálculoSCRIPT_INT ("
retornar tabpy.query ('teste_de_contagem_de_ pessoas', _ arg1, _arg2) ['resposta']
", SUM ([pessoas]), ATTR ([fruits_id]))
Arquivo .Pydo cliente de importação clickhouse_driver
import tabpy_client
connection = tabpy_client.Client ('http: // localhost: 9004 /')
def unique_people_count (people, fruit_id):
cliente = cliente (host = nome do host, banco de dados = nome do banco de dados, usuário = nome do usuário, senha = senha)

----- script_text -----

connection.deploy ('people_count_test', unique_people_count, 'comment', override = True)
Aqui você pode ver que 'people_count_test' é o identificador do TabPy Client, graças ao qual fica claro qual script executar neste campo Cálculo.

E, no final, foi essa abordagem que nos satisfez completamente.

imagem

Sumário


Os usuários estão satisfeitos porque podem escolher arbitrariamente uma combinação de "frutas" e obter rapidamente o número de fãs de pelo menos um deles, e os números em diferentes partes do painel são os mesmos.

Os desenvolvedores de BI têm o prazer de poder trabalhar com o ClickHouse do Tableau, sem precisar se conectar diretamente a ele.

Nosso Tableau Server tem o prazer de não precisar fazer uma extração enorme à noite.

Em geral, o TabPy oferece aos desenvolvedores de BI mais liberdade para trabalhar com dados quando o Tableau não possui uma solução adequada pronta para uso. Por exemplo, para incorporar modelos de ciência de dados diretamente no Tableau, mas isso é outra história ...

O artigo foi escrito em conjunto com meus colegas Dimitri Shcherbenko ( dima_vs ) e Sukhoveev Ivan ( suho_v ) P&D Dentsu Aegis Network Russia.

Source: https://habr.com/ru/post/pt477864/


All Articles