Ubuntu TechHive
discover-clickhouse-a-highperformance-columnoriented-dbms-for-olap-and-realtime-analytics.md
Discover Clickhouse: A high-performance Column-Oriented DBMS for OLAP and Real-Time Analytics
article.detalhe

Discover Clickhouse: A high-performance Column-Oriented DBMS for OLAP and Real-Time Analytics

reading.progresso 15 min de leitura

Descrição do Discover Clickhouse

Introdução a Bancos de Dados

O que é um Banco de Dados?

Um banco de dados é um sistema usado para armazenar, organizar e acessar informações. Ele permite que os usuários insiram, gerenciem e recuperem dados de forma eficiente e segura. Os bancos de dados são estruturados para lidar com grandes quantidades de informações, permitindo que os dados sejam armazenados em tabelas que podem ser pesquisadas, manipuladas e mantidas facilmente.

Une base de données est un système utilisé pour stocker,iser et accéder à des informations. Elle permet aux utilisateurs de saisir, gérer et récupérer des données de manière efficace et sécurisée. Les bases de données sont structurées pour gérer de grandes quantités d'informations en permettant que les données soient stockées dans des tables qui peuvent être recherchées, manipulées et entretenues facilement.

Tipos de Bancos de Dados

Relacional Armazena dados em tabelas estruturadas com linhas e colunas, permitindo consultas complexas usando SQL. Exemplo: banco de dados de RH e CRM.

Não relacional Lida com dados não estruturados e semiestruturados sem uma estrutura de tabela fixa, usando formatos como chave-valor, documentos e grafos. Exemplo: plataformas de e-commerce, gerenciamento de conteúdo, IoT e análises em tempo real.

Introdução aos Sistemas de Gerenciamento de Banco de Dados (SGBD)

Software que permite aos usuários definir, criar, manter e controlar o acesso ao banco de dados. Ele gerencia o armazenamento, manipulação e recuperação de dados, facilitando múltiplas interações de usuários com vários bancos de dados.

Logiciel permettant aux utilisateurs de définir, créer, maintenir et contrôler l'accès à la base de données. Il gère le stockage, la manipulation et la récupération des données, facilitant les interactions de plusieurs utilisateurs avec diverses bases de données.

Fundamentos de Bancos de Dados Orientados a Colunas

Armazenamento Orientado a Linhas vs. Orientado a Colunas

Bancos de Dados Orientados a Linhas:- Estrutura: Armazena dados por linhas, tornando-o eficiente para operações de escrita e processamento transacional onde o acesso a registros completos é comum.

  • Benefícios: Ideal para sistemas OLTP (Online Transaction Processing), como gerenciamento de relacionamento com o cliente, onde atualizações e inserções rápidas são cruciais.

Bancos de Dados Orientados a Colunas:- Estrutura: Armazena dados por colunas, aprimorando operações de leitura e análise de dados onde agregações sobre grandes conjuntos de dados são necessárias.

  • Benefícios: Ideal para sistemas OLAP (Online Analytical Processing), como data warehousing e análise de big data, oferecendo alto desempenho para consultas que acessam apenas um subconjunto de colunas.

Vantagens:- Orientado a Linhas: Recuperação rápida de dados por linha completa, implementação mais simples, eficiente para entrada e atualização de registros.

  • Orientado a Colunas: Melhor compressão, armazenamento eficiente que leva a uma leitura mais rápida dos dados da coluna, otimizado para consultar grandes conjuntos de dados, o que reduz as operações de E/S.

Bases de données orientées ligne :- Estrutura: Armazena dados por linhas, o que é eficiente para operações de escrita e processamento transacional onde o acesso a registros completos é comum.

  • Vantagens: Ideal para sistemas OLTP (Processamento de Transações Online), como gerenciamento de relacionamento com o cliente, onde atualizações e inserções rápidas são cruciais.

Bancos de dados orientados a colunas:- Estrutura: Armazena dados por colunas, melhorando as operações de leitura e análise de dados onde agregações em grandes conjuntos de dados são necessárias.

  • Vantagens: Ideal para sistemas OLAP (Processamento Analítico Online), como armazenamento de dados e análise de big data, oferecendo alto desempenho para consultas que acessam apenas um subconjunto de colunas.

Vantagens:- Orientado a linha: Recuperação rápida de dados por linha completa, implementação mais simples, eficaz para entrada e atualização de registros.

  • Orientado a coluna: Melhor compressão, armazenamento eficiente levando a uma leitura rápida de dados de coluna, otimizado para consulta de grandes conjuntos de dados, o que reduz as operações de entrada/saída.

Banco de Dados Orientado a Colunas

graph TD
subgraph "Banco de Dados Orientado a Colunas"
subgraph "Coluna ID"
ID1 [1]
ID2 [2]
ID3 [3]
end
subgraph "Coluna Nome"
Name1 [John]
Name2 [Alice]
Name3 [Bob]
end
subgraph "Coluna Idade"
Age1 [30]
Age2 [25]
Age3 [35]
end
subgraph "Coluna Cidade"
City1 [New York]
City2 [Los Angeles]
City3 [San Francisco]
end
end

Banco de Dados Orientado a Linhas

graph TD
subgraph "Armazenamento Orientado a Linhas"
A ["Linha 1: ID | Name | Age | City"]
B ["Linha 2: ID | Name | Age | City"]
C ["Linha 3: ID | Name | Age | City"]
end

Introdução ao ClickHouse

O que é ClickHouse?

ClickHouse é um sistema de gerenciamento de banco de dados (SGBD) orientado a colunas de código aberto, projetado para processamento analítico online (OLAP). Ele permite que os usuários gerem relatórios analíticos usando consultas SQL em tempo real, oferecendo alto desempenho e escalabilidade para processar grandes volumes de dados. As principais características incluem:

  • Armazenamento orientado a colunas

  • Compressão de dados

  • Processamento de consultas distribuído

  • Suporte SQL

  • Alto desempenho para consultas analíticas

  • Capacidade de lidar com petabytes de dados

  • Tolerância a falhas através de replicação

ClickHouse é particularmente adequado para aplicações que exigem análises rápidas em conjuntos de dados massivos, como inteligência de negócios, observabilidade e data warehousing em tempo real.

ClickHouse é um sistema de gerenciamento de banco de dados (SGBD) orientado a colunas e de código aberto, projetado para processamento analítico online (OLAP). Ele permite que os usuários gerem relatórios analíticos em tempo real usando consultas SQL, oferecendo alto desempenho e escalabilidade para o processamento de grandes volumes de dados. As principais características incluem:

  • Armazenamento orientado a colunas

  • Compressão de dados

  • Processamento distribuído de consultas

  • Suporte SQL

  • Alto desempenho para consultas analíticas

  • Capacidade de gerenciar petabytes de dados

  • Tolerância a falhas através de replicação

ClickHouse é particularmente adequado para aplicações que exigem análises rápidas em conjuntos de dados massivos, como inteligência de negócios, observabilidade e armazenamento de dados em tempo real.

Principais Recursos do ClickHouse e Velocidade

  • Armazenamento Orientado a Colunas: Frequentemente, apenas algumas das centenas de colunas nos dados de origem são necessárias para um relatório. O armazenamento orientado a colunas melhora a eficiência ao acessar apenas as colunas necessárias, reduzindo leituras de disco dispendiosas.

  • Índices: O ClickHouse utiliza estruturas de dados em memória para ler apenas as colunas necessárias e intervalos de linhas específicos, otimizando a recuperação de dados.

  • Compressão de Dados: Agrupar os valores da mesma coluna melhora a compressão em comparação com sistemas orientados a linhas, pois valores semelhantes são comuns em linhas adjacentes. O ClickHouse também emprega codecs especializados para uma compactação de dados ainda maior.

  • Execução de Consulta Vetorizada: O ClickHouse processa dados por colunas, melhorando a eficiência do cache da CPU e permitindo o uso de instruções SIMD da CPU para operações mais rápidas.

  • Escalabilidade: O ClickHouse maximiza a utilização de recursos aproveitando todos os núcleos de CPU e discos disponíveis, não apenas em um único servidor, mas em um cluster, melhorando o desempenho para consultas complexas.

  • Armazenamento orientado a colunas: Frequentemente, apenas algumas das centenas de colunas dos dados de origem são necessárias para um relatório. O armazenamento orientado a colunas melhora a eficiência acessando apenas as colunas necessárias, reduzindo assim as custosas leituras de disco.

  • Índice *: O ClickHouse utiliza estruturas de dados em memória para ler apenas as colunas necessárias e as faixas de linhas específicas, otimizando assim a recuperação de dados.

  • Compressão de dados: Agrupar os valores de uma mesma coluna melhora a compressão em comparação com os sistemas orientados a linha, pois valores semelhantes são comuns em linhas adjacentes. O ClickHouse também utiliza codecs especializados para uma compacidade ainda maior dos dados.

  • Execução de consultas vetorizadas: O ClickHouse processa os dados por colunas, melhorando a eficiência do cache da CPU e permitindo o uso de instruções SIMD da CPU para operações mais rápidas.

  • Escalabilidade: O ClickHouse maximiza o uso dos recursos explorando todos os núcleos de CPU e discos disponíveis, não apenas em um único servidor, mas em todo um cluster, melhorando assim o desempenho para consultas complexas.

Chave Primária, Índice e Granule

Chave Primária:

  • Determina a ordem de classificação física dos dados no disco

  • Usado para criar um índice esparso

Índice:

  • O índice é criado para cada N linhas (padrão 8192), chamado de grânulo

  • Armazenado no arquivo primary.idx

  • Usado para localizar rapidamente blocos de dados relevantes

Grânulos:

  • Um grânulo é um grupo lógico de linhas (padrão 8192 linhas)

  • Os dados são divididos em várias partes, e cada parte é dividida em grânulos

Como eles funcionam juntos:

  • Quando uma consulta é executada, o ClickHouse usa a chave primária para pesquisar o índice esparso

  • O índice ajuda a identificar quais grânulos podem conter dados relevantes

  • O ClickHouse então carrega apenas os grânulos correspondentes na memória

  • Os dados dentro dos grânulos são processados para encontrar as linhas exatas correspondentes

Arquitetura do ClickHouse

Visão Geral da Arquitetura do ClickHouse

  • Motor O motor ClickHouse é um tipo de motor de tabela que determina como e onde os dados são armazenados, como as consultas são executadas e as capacidades de concorrência e replicação da base de dados. Cada motor é otimizado para casos de uso específicos, fornecendo várias funcionalidades, como particionamento de dados, indexação e suporte para diferentes tipos de consulta.

  • Moteur : Le moteur ClickHouse est un type de moteur de table qui détermine comment et où les données sont stockées, comment les requêtes sont exécutées, ainsi que les capacités de concurrence et de réplication de la base de données. Chaque moteur est optimisé pour des cas d'utilisation spécifiques, offrant diverses fonctionnalités telles que le partitionnement des données, l'indexation et le support pour différents types de requêtes.

Motores ClickHouse

Família MergeTree:

  • MergeTree: O motor mais versátil e comumente usado, projetado para operações de leitura e escrita de alto desempenho, suportando particionamento de dados, chaves primárias e replicação de dados.

  • ReplacingMergeTree: Permite a deduplicação de linhas durante as fusões com base na chave de ordenação.

  • SummingMergeTree: Soma colunas numéricas para linhas com a mesma chave de ordenação durante as fusões.

  • AggregatingMergeTree: Agrega dados durante as fusões usando funções de agregação especificadas.

  • CollapsingMergeTree: Colapsa linhas com a mesma chave de ordenação durante as fusões, com base em uma coluna especial 'Sign'.

  • VersionedCollapsingMergeTree: Estende o CollapsingMergeTree com controle de versão para linhas.

  • GraphiteMergeTree: Especializado para armazenar dados de séries temporais.

Motores de Integração:

  • ODBC: Permite consultar bancos de dados externos usando ODBC.

  • JDBC: Permite consultar bancos de dados externos usando JDBC.

  • MySQL: Para consultar bancos de dados MySQL.

  • MongoDB: Permite consultar bancos de dados MongoDB.

  • HDFS: Para trabalhar com dados armazenados no Hadoop Distributed File System.

  • S3: Permite trabalhar com dados armazenados no Amazon S3.

  • Kafka: Para trabalhar com fluxos Apache Kafka.

  • Famille MergeTree :

  • MergeTree : Le moteur le plus polyvalent et le plus utilisé, conçu pour des opérations de lecture et d'écriture à haute performance, prenant en charge le partitionnement des données, les clés primaires et la réplication des données.

  • ReplacingMergeTree : Permet la déduplication des lignes pendant les fusions basées sur la clé de tri.

  • SummingMergeTree : Somme les colonnes numériques pour les lignes ayant la même clé de tri pendant les fusions.

  • AggregatingMergeTree : Agrège les données pendant les fusions en utilisant des fonctions d'agrégation spécifiées.

  • CollapsingMergeTree: Colapsa linhas com a mesma chave de ordenação durante as fusões, com base em uma coluna especial 'Signo'.

  • VersionedCollapsingMergeTree: Estende CollapsingMergeTree com controle de versão para as linhas.

  • GraphiteMergeTree: Especializado para o armazenamento de dados de séries temporais.

Começando com ClickHouse

Instalação e Configuração - no Mac ou Linux

  • Instalar biblioteca
curl https://clickhouse.com/ | sh
  • Execute o seguinte comando para iniciar o servidor ClickHouse:
./clickhouse server
  • Abra um novo Terminal e conecte-se ao servidor
clickhouse-client
  • Consultar arquivos remotos
- -Check the file
SELECT * FROM s3('https://clickhouse-public-datasets.s3.amazonaws.com/ontime/csv_by_year/*.csv.gz', CSVWithNames) limit 10;
  • -Contagem Básica
    SELECT count() FROM s3('https://clickhouse-public-datasets.s3.amazonaws.com/ontime/csv_by_year/*.csv.gz', CSVWithNames) limit 10;

  • -O número de atrasos por transportadora para 2007
    SELECT IATA_CODE_Reporting_Airline AS Carrier, count()
    FROM s3('https://clickhouse-public-datasets.s3.amazonaws.com/ontime/csv_by_year/
    .csv.gz')
    WHERE DepDelay>10 AND Year=2007
    GROUP BY Carrier
    ORDER BY count(*) DESC limit 5;


**Resultados** \\ ┌─Carrier─┬─count()─┐

- │ WN │ 296293 │ └─────────┴─────────┘ ┌─Carrier─┬─count()─┐

- │ AA │ 176203 │

- │ MQ │ 145630 │

- │ US │ 135987 │

- │ UA │ 128174 │ └─────────┴─────────┘

5 linhas no conjunto. Decorrido: 420.586 seg. Processado 204.84 milhões de linhas, 11.66 GB (487.03 mil linhas/s., 27.72 MB/s.) Pico de uso de memória: 1.18 GiB.

## Executando Sua Primeira Consulta

#### Criar tabela

CREATE TABLEontime
(
Year UInt16,
Quarter UInt8,
Month UInt8,
DayofMonth UInt8,
DayOfWeek UInt8,
FlightDate Date,
Reporting_Airline LowCardinality(String),
DOT_ID_Reporting_Airline Int32,
IATA_CODE_Reporting_Airline LowCardinality(String),
Tail_Number LowCardinality(String),
Flight_Number_Reporting_AirlineLowCardinality(String),
OriginAirportID Int32,
OriginAirportSeqID Int32,
OriginCityMarketID Int32,
Origin FixedString(5),
OriginCityName LowCardinality(String),
OriginState FixedString(2),

OriginStateFips FixedString(2),
OriginStateName LowCardinality(String),
OriginWac Int32,
DestAirportID Int32,
DestAirportSeqID Int32,
DestCityMarketID Int32,
Dest FixedString(5),
DestCityName LowCardinality(String),
DestState FixedString(2),
DestStateFips FixedString(2),
DestStateName LowCardinality(String),
DestWac Int32,
CRSDepTime Int32,
DepTime Int32,
DepDelay Int32,
DepDelayMinutes Int32,
DepDel15 Int32,
DepartureDelayGroups LowCardinality(String),

DepTimeBlk LowCardinality(String),
TaxiOut Int32,
WheelsOff LowCardinality(String),
WheelsOn LowCardinality(String),
TaxiIn Int32,
CRSArrTime Int32,
ArrTime Int32,
ArrDelay Int32,
ArrDelayMinutes Int32,
ArrDel15 Int32,
ArrivalDelayGroups LowCardinality(String),
ArrTimeBlk LowCardinality(String),
Cancelled Int8,
CancellationCode FixedString(1),
Diverted Int8,
CRSElapsedTime Int32,
ActualElapsedTime Int32,
AirTime Int32,

Flights Int32,
Distance Int32,
DistanceGroup Int8,
CarrierDelay Int32,
WeatherDelay Int32,
NASDelay Int32,
SecurityDelay Int32,
LateAircraftDelay Int32,
FirstDepTime Int16,
TotalAddGTime Int16,
LongestAddGTime Int16,
DivAirportLandings Int8,
DivReachedDest Int8,
DivActualElapsedTime Int16,
DivArrDelay Int16,
DivDistance Int16,
Div1Airport LowCardinality(String),
Div1AirportID Int32,
Div1AirportSeqID Int32,
Div1WheelsOn Int16,

Div1TotalGTime Int16,
Div1LongestGTime Int16,
Div1WheelsOff Int16,
Div1TailNum LowCardinality(String),
Div2Airport LowCardinality(String),
Div2AirportID Int32,
Div2AirportSeqID Int32,
Div2WheelsOn Int16,
Div2TotalGTime Int16,
Div2LongestGTime Int16,
Div2WheelsOff Int16,
Div2TailNum LowCardinality(String),
Div3Airport LowCardinality(String),
Div3AirportID Int32,
Div3AirportSeqID Int32,
Div3WheelsOn Int16,
Div3TotalGTime Int16,
Div3LongestGTime Int16,
Div3WheelsOff Int16,

Div3TailNum LowCardinality(String),
Div4Airport LowCardinality(String),
Div4AirportID Int32,
Div4AirportSeqID Int32,
Div4WheelsOn Int16,
Div4TotalGTime Int16,
Div4LongestGTime Int16,
Div4WheelsOff Int16,
Div4TailNum LowCardinality(String),
Div5Airport LowCardinality(String),
Div5AirportID Int32,
Div5AirportSeqID Int32,
Div5WheelsOn Int16,
Div5TotalGTime Int16,
Div5LongestGTime Int16,
Div5WheelsOff Int16,
Div5TailNum LowCardinality(String)
) ENGINE = MergeTree

ORDER BY (Year, Quarter, Month, DayofMonth, FlightDate, IATA_CODE_Reporting_Airline);


#### Carregar os dados - 1M de registros carregados e apenas 2002

INSERT INTO ontime SELECT *
FROM s3('https://clickhouse-public-datasets.s3.amazonaws.com/ontime/csv_by_year/2001.csv.gz', CSVWithNames)
WHERE Year=2001 limit 1000000
SETTINGS max_insert_threads = 40;


- Número de atrasos por aeroporto

SELECT Origin, count(*) AS c
FROM ontime
WHERE DepDelay>10
GROUP BY Origin
ORDER BY c DESC
LIMIT 10;


#### Consultar dados locais - O arquivo é local

Usando o conjunto de dados de Reclamações de NY.

[RECLAMAÇÕES DA NYPD](https://data.cityofnewyork.us/Public-Safety/NYPD-Complaint-Data-Current-Year-To-Date-/5uac-w243/about_data)

describe table file("/Users/ [you]/user_files/nypd_complaint.tsv")

select * from file("/Users/ [you]/user_files/nypd_complaint.tsv") limit 10


##### Análise rápida

- Contagem de Reclamações por tipo de Crime

SELECT IFNULL(NYPD_Complaint_Data_Current_Year_To_Date.OFNS_DESC, 'Unknown') AS Crime_Type,
COUNT(*) AS Complaint_Count
FROM url('https://data.cityofnewyork.us/api/views/5uac-w243/rows.csv?accessType=DOWNLOAD', CSVWithNames)
AS NYPD_Complaint_Data_Current_Year_To_Date
GROUP BY Crime_Type ORDER BY Complaint_Count DESC limit 10


- Crimes Mais Comuns à Noite

SELECT IFNULL(NYPD_Complaint.OFNS_DESC, 'Unknown') AS Crime_Type,
COUNT(*) AS Complaint_Count
FROM url('https://data.cityofnewyork.us/api/views/5uac-w243/rows.csv?accessType=DOWNLOAD', CSVWithNames)
AS NYPD_Complaint

WHERE (NYPD_Complaint.CMPLNT_FR_TM>= '18:00:00' OR NYPD_Complaint.CMPLNT_FR_TM<= '06:00:00')
GROUP BY Crime_Type ORDER BY Complaint_Count DESC limit 10

Começando com o ClickHouse Cloud

Clickhouse Cloud

chDB - Uma Visão Geral

Visão Geral

chDB é um motor SQL OLAP (Online Analytical Processing) em processo alimentado por ClickHouse. Ele foi projetado para ser um banco de dados embarcado que leva o poder do ClickHouse para aplicações sem a necessidade de uma instalação de servidor separada. chDB é desenvolvido pela ClickHouse, Inc. e colaboradores de código aberto.

As principais características do chDB incluem:

  • Operação sem servidor - sem necessidade de instalar ou executar serviços ClickHouse

  • Suporte para múltiplas linguagens de programação, incluindo Python, Go, Rust, NodeJS e Bun

  • Capacidade de trabalhar com vários formatos de dados como Parquet, CSV, JSON, Arrow e ORC

  • Funções Definidas pelo Usuário (UDFs) personalizadas

chDB é um motor OLAP (Online Analytical Processing) SQL em execução, alimentado por ClickHouse. Ele é projetado para ser um banco de dados embarcado que traz o poder do ClickHouse para aplicações sem a necessidade de uma instalação de servidor separada. chDB é desenvolvido pela ClickHouse, Inc. e por contribuidores de código aberto.

As principais características do chDB incluem:

  • Operação sem servidor - não há necessidade de instalar ou executar serviços ClickHouse

  • Suporte para várias linguagens de programação, incluindo Python, Go, Rust, NodeJS e Bun

  • Capacidade de trabalhar com vários formatos de dados como Parquet, CSV, JSON, Arrow e ORC

  • Funções definidas pelo usuário (UDFs) personalizadas

Caso de Uso - Por que usar o chDB

Com base nas informações fornecidas, aqui estão alguns casos de uso práticos para o chDB em aplicações do mundo real:

  • Análise de dados em notebooks Jupyter: o chDB permite que os usuários executem consultas ClickHouse diretamente em notebooks Jupyter, tornando conveniente para cientistas e analistas de dados trabalhar com grandes conjuntos de dados sem a necessidade de um servidor ClickHouse separado.

  • Análise incorporada em aplicações: Desenvolvedores podem incorporar o chDB em suas aplicações para fornecer recursos analíticos rápidos sem a necessidade de um servidor de banco de dados separado.

  • Processamento de grandes conjuntos de dados localmente: o chDB permite o processamento de grandes conjuntos de dados (por exemplo, arquivos Parquet, CSV, JSON) em uma máquina local sem a necessidade de configurar um sistema de banco de dados completo.

  • Prototipagem rápida: Engenheiros e analistas de dados podem prototipar e testar rapidamente consultas em grandes conjuntos de dados sem implantar um cluster ClickHouse completo.

  • Ambientes serverless: o chDB pode ser usado em funções serverless para fornecer recursos analíticos sem gerenciar a infraestrutura do banco de dados.

  • Processamento de pipeline de dados: o chDB pode ser integrado em pipelines de dados para transformações e agregações rápidas de dados.

Basé sur les informations fournies, voici quelques cas d'utilisation pratiques de chDB dans des applications réelles :

  • Analyse de données dans les notebooks Jupyter : chDB permet aux utilisateurs d'exécuter des requêtes ClickHouse directement dans des notebooks Jupyter, facilitant ainsi le travail des data scientists et analystes sur de grands ensembles de données sans avoir besoin d'un serveur ClickHouse séparé.

  • Analytique embarquée dans les applications : Les développeurs peuvent intégrer chDB dans leurs applications pour fournir des capacités analytiques rapides sans nécessiter un serveur de base de données séparé.

  • Processamento local de grandes conjuntos de dados: o chDB permite processar grandes conjuntos de dados (por exemplo, Parquet, CSV, arquivos JSON) em uma máquina local sem a necessidade de configurar um sistema de banco de dados completo.

  • Prototipagem rápida: Engenheiros de dados e analistas podem prototipar e testar rapidamente consultas em grandes conjuntos de dados sem implantar um cluster ClickHouse completo.

  • Ambientes sem servidor: o chDB pode ser usado em funções serverless para fornecer recursos analíticos sem a necessidade de gerenciar uma infraestrutura de banco de dados.

  • Processamento de pipelines de dados: o chDB pode ser integrado em pipelines de dados para transformações e agregações rápidas de dados.

Demonstração - google collab

Google Collab

Referências: