RESUMO
1 INTRODUÇÃO
- Conjuntos de dados enormes com altas taxas de ingestão. Muitas aplicações orientadas por dados em setores como web analytics, finanças e comércio eletrônico são caracterizadas por volumes de dados enormes e em crescimento contínuo. Para lidar com grandes conjuntos de dados, os bancos de dados analíticos não devem apenas oferecer estratégias eficientes de indexação e compressão, mas também permitir a distribuição de dados entre vários nós (scale-out), já que um único servidor é limitado a algumas dezenas de terabytes de armazenamento. Além disso, dados recentes costumam ser mais relevantes para insights em tempo real do que dados históricos. Como resultado, bancos de dados analíticos devem ser capazes de fazer a ingestão de novos dados de forma consistente em altas taxas ou em rajadas, bem como “despriorizar” continuamente os dados históricos (por exemplo, agregando-os ou arquivando-os) sem desacelerar as consultas de relatórios executadas em paralelo.
- Muitas consultas simultâneas com expectativa de baixa latência. Em geral, as consultas podem ser categorizadas como ad hoc (por exemplo, análise exploratória de dados) ou recorrentes (por exemplo, consultas periódicas de dashboard). Quanto mais interativo for um caso de uso, menores serão as latências de consulta esperadas, o que traz desafios de otimização e execução de consultas. Consultas recorrentes também oferecem a oportunidade de adaptar o layout físico do banco de dados à carga de trabalho. Como resultado, os bancos de dados devem oferecer técnicas de poda que permitam otimizar consultas frequentes. Dependendo da prioridade da consulta, os bancos de dados também devem conceder acesso igualitário ou priorizado a recursos compartilhados do sistema, como CPU, memória, disco e E/S de rede, mesmo quando um grande número de consultas é executado simultaneamente.
- Ambientes diversos de armazenamentos de dados, locais de armazenamento e formatos. Para se integrarem a arquiteturas de dados existentes, os bancos de dados analíticos modernos devem apresentar um alto grau de abertura para ler e gravar dados externos em qualquer sistema, local ou formato.
- Uma linguagem de consulta prática com suporte à introspecção de desempenho. O uso de bancos de dados OLAP no mundo real impõe requisitos “mais brandos” adicionais. Por exemplo, em vez de uma linguagem de programação de nicho, os usuários frequentemente preferem interagir com bancos de dados por meio de um dialeto SQL expressivo com tipos de dados aninhados e uma ampla variedade de funções regulares, de agregação e de janela. Bancos de dados analíticos também devem fornecer ferramentas sofisticadas para inspecionar o desempenho do sistema ou de consultas individuais.
- Robustez de nível industrial e implantação versátil. Como hardware comum não é confiável, os bancos de dados devem fornecer replicação de dados para garantir robustez contra falhas de nós. Além disso, os bancos de dados devem funcionar em qualquer hardware, de laptops antigos a servidores poderosos. Por fim, para evitar a sobrecarga da coleta de lixo em programas baseados em JVM e permitir desempenho bare-metal (por exemplo, SIMD), o ideal é que os bancos de dados sejam implantados como binários nativos para a plataforma de destino.

Figura 1: Linha do tempo do ClickHouse.
2 ARQUITETURA

Figura 2: A arquitetura de alto nível do mecanismo de banco de dados ClickHouse.
3 CAMADA DE ARMAZENAMENTO
Esta seção aborda os motores de tabela MergeTree* como o formato de armazenamento nativo do ClickHouse. Descrevemos sua representação em disco e discutimos três técnicas de poda de dados no ClickHouse. Em seguida, apresentamos estratégias de merge que transformam continuamente os dados sem afetar as inserções simultâneas. Por fim, explicamos como atualizações e exclusões são implementadas, bem como a desduplicação de dados, a replicação de dados e a conformidade com ACID.3.1 Formato em disco
Cada tabela com table engine MergeTree* é organizada como uma coleção de partes imutáveis da tabela. Uma parte é criada sempre que um conjunto de linhas é inserido na tabela. As partes são autocontidas no sentido de que incluem todos os metadados necessários para interpretar seu conteúdo sem consultas adicionais a um catálogo central. Para manter baixo o número de partes por tabela, um processo de merge em segundo plano combina periodicamente várias partes menores em uma parte maior até atingir um tamanho de parte configurável (150 GB por padrão). Como as partes são ordenadas pelas colunas da chave primária da tabela (consulte a Seção 3.2), usa-se uma ordenação por intercalação k-way eficiente [40] para o merging. As partes de origem são marcadas como inativas e acabam sendo excluídas assim que sua contagem de referências cai para zero, ou seja, quando nenhuma consulta mais as lê. As linhas podem ser inseridas em dois modos: no modo de inserção síncrona, cada instrução INSERT cria uma nova parte e a adiciona à tabela. Para minimizar a sobrecarga dos merges, recomenda-se que os clientes do banco de dados insiram tuplas em massa, por exemplo, 20.000 linhas de uma só vez. No entanto, atrasos causados pelo batching no lado do cliente costumam ser inaceitáveis quando os dados precisam ser analisados em tempo real. Por exemplo, casos de uso de observabilidade frequentemente envolvem milhares de agentes de monitoramento enviando continuamente pequenas quantidades de dados de eventos e métricas. Esses cenários podem usar o modo de inserção assíncrona, no qual o ClickHouse armazena em buffer linhas de vários INSERTs recebidos na mesma tabela e cria uma nova parte somente depois que o tamanho do buffer excede um limite configurável ou um timeout expira.
Figura 3: Inserts e merges para tabelas com engine MergeTree*.
3.2 Poda de dados
Na maioria dos casos de uso, varrer petabytes de dados apenas para responder a uma única consulta é lento e caro demais. O ClickHouse oferece suporte a três técnicas de poda de dados que permitem ignorar a maior parte das linhas durante as buscas e, assim, acelerar significativamente as consultas. Primeiro, os usuários podem definir um índice de chave primária para uma tabela. As colunas da chave primária determinam a ordem de classificação das linhas dentro de cada parte, ou seja, o índice é clusterizado localmente. Além disso, o ClickHouse armazena, para cada parte, um mapeamento entre os valores da coluna de chave primária da primeira linha de cada grânulo e o id do grânulo, ou seja, o índice é esparso [31]. A estrutura de dados resultante normalmente é pequena o suficiente para permanecer inteiramente em memória; por exemplo, apenas 1000 entradas são necessárias para indexar 8,1 milhões de linhas. O principal objetivo de uma chave primária é avaliar predicados de igualdade e de intervalo em colunas filtradas com frequência usando busca binária em vez de varreduras sequenciais (Seção 4.4). A ordenação local também pode ser explorada para mesclagem de partes e otimização de consultas, por exemplo, agregação baseada em ordenação ou remoção de operadores de ordenação do plano físico de execução quando as colunas da chave primária formam um prefixo das colunas de ordenação. A Figura 4 mostra um índice de chave primária na coluna EventTime para uma tabela com estatísticas de impressões de página. Os grânulos que correspondem ao predicado de intervalo na consulta podem ser encontrados por busca binária no índice de chave primária, em vez de percorrer EventTime sequencialmente.
Figura 4: Avaliação de filtros com um índice de chave primária.
3.3 Transformação de dados durante a mesclagem
Casos de uso de inteligência de negócios e observabilidade frequentemente precisam lidar com dados gerados em taxas constantemente altas ou em picos. Além disso, dados gerados recentemente costumam ser mais relevantes para obter insights significativos em tempo real do que dados históricos. Esses casos de uso exigem que os bancos de dados sustentem altas taxas de ingestão de dados enquanto reduzem continuamente o volume de dados históricos por meio de técnicas como agregação ou expiração de dados. O ClickHouse permite a transformação incremental contínua dos dados existentes usando diferentes estratégias de mesclagem. A transformação de dados durante a mesclagem não compromete o desempenho das instruções INSERT, mas não pode garantir que as tabelas nunca contenham valores indesejados (por exemplo, desatualizados ou não agregados). Se necessário, todas as transformações durante a mesclagem podem ser aplicadas no momento da consulta especificando a palavra-chave FINAL em instruções SELECT. Mesclagens de substituição mantêm apenas a versão de uma tupla inserida mais recentemente, com base no timestamp de criação da parte que a contém; as versões mais antigas são excluídas. As tuplas são consideradas equivalentes se tiverem os mesmos valores nas colunas da chave primária. Para controlar explicitamente qual tupla é preservada, também é possível especificar uma coluna de versão especial para comparação. Mesclagens de substituição são comumente usadas como mecanismo de atualização durante a mesclagem (normalmente em casos de uso em que atualizações são frequentes) ou como alternativa à desduplicação de dados no momento da inserção (Seção 3.5). Mesclagens de agregação colapsam linhas com os mesmos valores nas colunas da chave primária em uma linha agregada. As colunas que não fazem parte da chave primária devem ser de um estado de agregação parcial que contenha os valores resumidos. Dois estados de agregação parciais, por exemplo, uma soma e uma contagem para avg(), são combinados em um novo estado de agregação parcial. Mesclagens de agregação são normalmente usadas em visões materializadas em vez de tabelas normais. Visões materializadas são preenchidas com base em uma consulta de transformação sobre uma tabela de origem. Ao contrário de outros bancos de dados, o ClickHouse não atualiza visões materializadas periodicamente com todo o conteúdo da tabela de origem. Em vez disso, visões materializadas são atualizadas incrementalmente com o resultado da consulta de transformação quando uma nova parte é inserida na tabela de origem. A Figura 5 mostra uma visão materializada definida sobre uma tabela com estatísticas de impressões de página. Para novas partes inseridas na tabela de origem, a consulta de transformação calcula as latências máxima e média, agrupadas por região, e insere o resultado em uma visão materializada. As funções de agregação avg() e max() com a extensão -State retornam estados de agregação parciais em vez de resultados finais. Uma mesclagem de agregação definida para a visão materializada combina continuamente estados de agregação parciais em diferentes partes. Para obter o resultado final, os usuários consolidam os estados de agregação parciais na visão materializada usando avg() e max()) com a extensão -Merge.
Figura 5: Mesclagens de agregação em visões materializadas.
3.4 Atualizações e Exclusões
O design dos motores de tabela MergeTree* favorece cargas de trabalho append-only, mas alguns casos de uso exigem modificar dados existentes ocasionalmente, por exemplo, para conformidade regulatória. Existem duas abordagens para atualizar ou excluir dados, e nenhuma delas bloqueia inserções paralelas. Mutações reescrevem todas as partes de uma tabela in-place. Para evitar que uma tabela (exclusão) ou coluna (atualização) dobre temporariamente de tamanho, essa operação não é atômica, ou seja, instruções SELECT paralelas podem ler partes mutadas e não mutadas. As mutações garantem que os dados sejam alterados fisicamente ao final da operação. As mutações de exclusão ainda são caras, pois reescrevem todas as colunas em todas as partes. Como alternativa, exclusões leves atualizam apenas uma coluna interna de bitmap, indicando se uma linha foi excluída ou não. O ClickHouse acrescenta às consultas SELECT um filtro adicional na coluna de bitmap para excluir as linhas removidas do resultado. As linhas excluídas são removidas fisicamente apenas por mesclagens regulares, em algum momento futuro não especificado. Dependendo da quantidade de colunas, exclusões leves podem ser muito mais rápidas do que mutações, ao custo de SELECTs mais lentos. Espera-se que operações de atualização e exclusão na mesma tabela sejam raras e serializadas para evitar conflitos lógicos.3.5 Inserções idempotentes
Um problema que ocorre com frequência na prática é como os clientes devem lidar com timeouts de conexão após enviar dados ao servidor para inserção em uma tabela. Nessa situação, é difícil para os clientes determinar se os dados foram inseridos com sucesso ou não. Tradicionalmente, esse problema é resolvido reenviando os dados do cliente para o servidor e contando com a chave primária ou com restrições de unicidade para rejeitar inserts duplicados. Os bancos de dados realizam rapidamente as consultas pontuais necessárias usando estruturas de índice baseadas em árvores binárias [39, [68]](#page-13-16), árvores radix [45] ou tabelas hash [29]. Como essas estruturas de dados indexam cada tupla, sua sobrecarga de espaço e de atualização se torna proibitiva para grandes volumes de dados e altas taxas de ingestão. O ClickHouse oferece uma alternativa mais leve baseada no fato de que cada insert acaba criando uma parte. Mais especificamente, o servidor mantém hashes das N últimas partes inseridas (por exemplo, N=100) e ignora reinserções de partes com hash conhecido. Os hashes de tabelas não replicadas e replicadas são armazenados localmente e no Keeper, respectivamente. Como resultado, os inserts se tornam idempotentes, ou seja, os clientes podem simplesmente reenviar o mesmo lote de linhas após um timeout e presumir que o servidor cuida da desduplicação. Para ter mais controle sobre o processo de desduplicação, os clientes podem, opcionalmente, fornecer um token de insert que atua como hash da parte. Embora a desduplicação baseada em hash gere uma sobrecarga associada ao cálculo do hash das novas linhas, o custo de armazenar e comparar hashes é insignificante.3.6 Replicação de dados
A replicação é um pré-requisito para alta disponibilidade (tolerância a falhas de nós), mas também é usada para balanceamento de carga e upgrades sem indisponibilidade [14]. No ClickHouse, a replicação se baseia no conceito de estados da tabela, que consistem em um conjunto de partes da tabela (Seção 3.1) e metadados da tabela, como nomes de colunas e tipos. Os nós fazem o estado de uma tabela avançar usando três operações: 1. inserções adicionam uma nova parte ao estado, 2. mesclagens adicionam uma nova parte e removem partes existentes do estado, 3. mutações e instruções DDL adicionam partes, e/ou removem partes, e/ou alteram os metadados da tabela, dependendo da operação específica. As operações são executadas localmente em um único nó e registradas como uma sequência de transições de estado em um log global de replicação. O log de replicação é mantido por um conjunto de, normalmente, três processos do ClickHouse Keeper, que usam o algoritmo de consenso Raft [59] para fornecer uma camada de coordenação distribuída e tolerante a falhas para um cluster de nós do ClickHouse. Inicialmente, todos os nós do cluster apontam para a mesma posição no log de replicação. Enquanto os nós executam localmente inserções, mesclagens, mutações e instruções DDL, o log de replicação é reproduzido de forma assíncrona em todos os outros nós. Como resultado, tabelas replicadas são apenas eventualmente consistentes, ou seja, os nós podem temporariamente ler estados antigos da tabela enquanto convergem para o estado mais recente. A maioria das operações mencionadas acima também pode ser executada de forma síncrona até que um quórum de nós (por exemplo, a maioria dos nós ou todos os nós) adote o novo estado. Como exemplo, a Figura 6 mostra uma tabela replicada inicialmente vazia em um cluster de três nós do ClickHouse. O Nó 1 primeiro recebe duas instruções de inserção e as registra ( 1 2 ) no log de replicação armazenado no conjunto do Keeper. Em seguida, o Nó 2 reproduz a primeira entrada do log buscando-a ( 3 ) e baixando a nova parte do Nó 1 ( 4 ), enquanto o Nó 3 reproduz ambas as entradas do log ( 3 4 5 6 ). Por fim, o Nó 3 faz merge das duas partes em uma nova parte, remove as partes de entrada e registra uma entrada de merge no log de replicação ( 7 ).
Figura 6: Replicação em um cluster de três nós.
3.7 Conformidade com ACID
Para maximizar o desempenho de operações concorrentes de leitura e escrita, o ClickHouse evita ao máximo o uso de travas. As consultas são executadas sobre um snapshot de todas as partes de todas as tabelas envolvidas, criado no início da consulta. Isso garante que novas partes inseridas por INSERTs paralelos ou mesclagens (Seção 3.1) não participem da execução. Para evitar que as partes sejam modificadas ou removidas ao mesmo tempo (Seção 3.4), a contagem de referências das partes processadas é incrementada durante toda a consulta. Formalmente, isso corresponde ao isolamento por snapshot implementado por uma variante de MVCC [6] baseada em partes versionadas. Como resultado, as instruções em geral não são compatíveis com ACID, exceto no caso raro em que escritas concorrentes, no momento em que o snapshot é obtido, afetam cada uma apenas uma única parte. Na prática, a maioria dos casos de uso do ClickHouse com alta intensidade de escrita para tomada de decisão tolera até mesmo um pequeno risco de perda de dados novos em caso de queda de energia. O banco de dados tira proveito disso ao não forçar, por padrão, um commit (fsync) das partes recém-inseridas em disco, permitindo que o kernel agrupe as gravações em lote, ao custo de abrir mão da atomicidade.4 CAMADA DE PROCESSAMENTO DE CONSULTAS

Figura 7: Paralelização entre unidades SIMD, núcleos e nós.
4.1 Paralelização SIMD
4.2 Paralelização Multicore

Figura 8: Um plano de operadores físicos com três faixas.
4.3 Paralelização em Múltiplos Nós
4.4 Otimização Holística de Desempenho
Esta seção apresenta otimizações de desempenho importantes aplicadas a diferentes estágios da execução de consultas. Otimização de consultas. O primeiro conjunto de otimizações é aplicado sobre uma representação semântica da consulta obtida a partir da AST da consulta. Exemplos dessas otimizações incluem constant folding (por exemplo, concat(lower(‘a’),upper(‘b’)) se torna ‘aB’), extração de escalares de certas funções de agregação (por exemplo, sum(a2) se torna 2 * sum(a)), eliminação de subexpressões comuns e transformação de disjunções de filtros de igualdade em listas IN (por exemplo, x=c OR x=d se torna x IN (c,d)). Em seguida, a representação semântica otimizada da consulta é transformada em um plano lógico de operadores. As otimizações sobre o plano lógico incluem pushdown de filtros, reordenação da avaliação de funções e das etapas de ordenação, dependendo de qual delas é estimada como mais custosa. Por fim, o plano lógico da consulta é transformado em um plano físico de operadores. Essa transformação pode explorar as particularidades dos motores de tabela envolvidos. Por exemplo, no caso de um motor de tabela MergeTree, se as colunas de ORDER BY formarem um prefixo da chave primária, os dados podem ser lidos na ordem do disco, e os operadores de ordenação podem ser removidos do plano. Além disso, se as colunas de agrupamento em uma agregação formarem um prefixo da chave primária, o ClickHouse pode usar agregação por ordenação [33], isto é, agregar diretamente sequências com o mesmo valor nas entradas pré-ordenadas. Em comparação com a agregação por hash, a agregação por ordenação consome significativamente menos memória, e o valor agregado pode ser passado ao próximo operador imediatamente após o processamento de uma sequência. Compilação de consultas. O ClickHouse emprega compilação de consultas baseada em LLVM para fundir dinamicamente operadores adjacentes do plano [38, [53]](#page-13-0). Por exemplo, a expressão a * b + c + 1 pode ser combinada em um único operador em vez de três operadores. Além de expressões, o ClickHouse também usa compilação para avaliar várias funções de agregação de uma só vez (isto é, para GROUP BY) e para ordenação com mais de uma chave de ordenação. A compilação de consultas reduz o número de chamadas virtuais, mantém os dados em registradores ou caches de CPU e ajuda o preditor de desvios, já que menos código precisa ser executado. Além disso, a compilação em tempo de execução possibilita um amplo conjunto de otimizações, como otimizações lógicas e otimizações peephole implementadas em compiladores, e dá acesso às instruções de CPU mais rápidas disponíveis localmente. A compilação é iniciada apenas quando a mesma expressão regular, de agregação ou de ordenação é executada por diferentes consultas mais do que um número configurável de vezes. Os operadores de consulta compilados são armazenados em cache e podem ser reutilizados por consultas futuras.[7] Avaliação do índice de chave primária. O ClickHouse avalia condições WHERE usando o índice de chave primária se um subconjunto de cláusulas de filtro na forma normal conjuntiva da condição constituir um prefixo das colunas da chave primária. O índice de chave primária é analisado da esquerda para a direita em intervalos lexicograficamente ordenados de valores de chave. As cláusulas de filtro correspondentes a uma coluna da chave primária são avaliadas usando lógica ternária - todas verdadeiras, todas falsas ou uma mistura de verdadeiro e falso para os valores no intervalo. Neste último caso, o intervalo é dividido em subintervalos, que são analisados recursivamente. Há otimizações adicionais para funções em condições de filtro. Primeiro, as funções têm características que descrevem sua monotonicidade; por exemplo, toDayOfMonth(date) é monotônica por partes dentro de um mês. Essas características de monotonicidade permitem inferir se uma função produz resultados ordenados sobre intervalos ordenados de valores de chave de entrada. Segundo, algumas funções podem calcular a pré-imagem de um determinado resultado de função. Isso é usado para substituir comparações de constantes com chamadas de função nas colunas de chave por comparações do valor da coluna de chave com a pré-imagem. Por exemplo, toYear(k) = 2024 pode ser substituído por k >= 2024-01-01 && k < 2025-01-01. Data skipping. O ClickHouse tenta evitar leituras de dados em tempo de execução da consulta usando as estruturas de dados apresentadas na Seção 3.2. Além disso, filtros em diferentes colunas são avaliados sequencialmente em ordem decrescente de seletividade estimada, com base em heurísticas e estatísticas de coluna (opcionais). Somente fragmentos de dados que contenham pelo menos uma linha correspondente são passados ao próximo predicado. Isso reduz gradualmente a quantidade de dados lidos e o número de cálculos a serem realizados de predicado para predicado. A otimização só é aplicada quando pelo menos um predicado altamente seletivo está presente; caso contrário, a latência da consulta pioraria em comparação com a avaliação paralela de todos os predicados. Tabelas hash. As tabelas hash são estruturas de dados fundamentais para agregação e junções hash. Escolher o tipo certo de tabela hash é essencial para o desempenho. O ClickHouse instancia várias tabelas hash (mais de 30 em março de 2024) a partir de um modelo genérico de tabela hash, tendo como pontos de variação a função hash, o alocador, o tipo de célula e a política de redimensionamento. Dependendo do tipo de dado das colunas de agrupamento, da cardinalidade estimada da tabela hash e de outros fatores, a tabela hash mais rápida é selecionada individualmente para cada operador de consulta. Outras otimizações implementadas para tabelas hash incluem:- um layout em dois níveis com 256 subtabelas (com base no primeiro byte do hash) para dar suporte a conjuntos de chaves enormes,
- tabelas hash de string [79] com quatro subtabelas e diferentes funções hash para diferentes comprimentos de string,
- tabelas de lookup que usam a chave diretamente como índice do bucket (isto é, sem hashing) quando há poucas chaves,
- valores com hashes incorporados para resolver colisões mais rapidamente quando a comparação é cara (por exemplo, strings, ASTs),
- criação de tabelas hash com base em tamanhos previstos a partir de estatísticas de execução para evitar redimensionamentos desnecessários,
- alocação de várias tabelas hash pequenas com o mesmo ciclo de vida de criação/destruição em uma única slab de memória,
- limpeza instantânea de tabelas hash para reutilização usando contadores de versão por tabela hash e por célula,
- uso de prefetch de CPU (__builtin_prefetch) para acelerar a recuperação de valores após calcular o hash da chave.

Figura 9: Hash join paralelo com três partições de tabela hash.
4.5 Isolamento de carga de trabalho
O ClickHouse oferece controle de concorrência, limites de uso de memória e escalonamento de I/O, permitindo que os usuários isolem consultas em classes de carga de trabalho. Ao definir limites para recursos compartilhados (núcleos de CPU, DRAM e I/O de disco e de rede) para classes específicas de carga de trabalho, ele garante que essas consultas não afetem outras consultas críticas para o negócio. O controle de concorrência evita a superalocação de threads em cenários com um grande número de consultas concorrentes. Mais especificamente, o número de threads de trabalho por consulta é ajustado dinamicamente com base em uma proporção especificada em relação ao número de núcleos de CPU disponíveis. O ClickHouse rastreia os tamanhos, em bytes, das alocações de memória nos níveis de servidor, usuário e consulta e, assim, permite definir limites flexíveis de uso de memória. O overcommit de memória permite que as consultas usem memória livre adicional além da memória garantida, ao mesmo tempo que assegura limites de memória para outras consultas. Além disso, o uso de memória para cláusulas de agregação, sort e join pode ser limitado, fazendo com que o sistema recorra a algoritmos externos quando o limite de memória for excedido. Por fim, o escalonamento de I/O permite que os usuários restrinjam acessos a discos locais e remotos para classes de carga de trabalho com base em largura de banda máxima, requisições em andamento e política (por exemplo, FIFO, SFC [32]).5 CAMADA DE INTEGRAÇÃO
Aplicações de tomada de decisão em tempo real frequentemente dependem de acesso eficiente e de baixa latência a dados distribuídos em vários locais. Existem duas abordagens para disponibilizar dados externos em um banco de dados OLAP. No acesso a dados baseado em envio, um componente de terceiros faz a ponte entre o banco de dados e armazenamentos de dados externos. Um exemplo disso são ferramentas especializadas de extract-transform-load (ETL), que enviam dados remotos para o sistema de destino. No modelo baseado em extração, o próprio banco de dados se conecta a fontes de dados remotas e extrai dados para consulta em tabelas locais ou exporta dados para sistemas remotos. Embora as abordagens baseadas em envio sejam mais versáteis e comuns, elas implicam maior complexidade arquitetural e um gargalo de escalabilidade. Em contraste, a conectividade remota diretamente no banco de dados oferece recursos interessantes, como junções entre dados locais e remotos, ao mesmo tempo em que mantém a arquitetura geral simples e reduz o tempo para obtenção de insights. O restante da seção explora métodos de integração de dados baseados em extração no ClickHouse, voltados ao acesso a dados em locais remotos. Observamos que a ideia de conectividade remota em bancos de dados SQL não é nova. Por exemplo, o padrão SQL/MED [35], introduzido em 2001 e implementado pelo PostgreSQL desde 2011 [65], propõe foreign data wrappers como uma interface unificada para gerenciar dados externos. A máxima interoperabilidade com outros armazenamentos de dados e formatos de armazenamento é um dos objetivos de projeto do ClickHouse. Em março de 2024, o ClickHouse oferece, até onde sabemos, o maior número de opções nativas de integração de dados entre todos os bancos de dados analíticos. Conectividade externa. O ClickHouse fornece 50+ funções de tabela e motores de integração para conectividade com sistemas externos e locais de armazenamento, incluindo ODBC, MySQL, PostgreSQL, SQLite, Kafka, Hive, MongoDB, Redis, armazenamentos de objetos S3/GCP/Azure e vários lagos de dados. Nós as dividimos ainda mais nas categorias mostradas na figura bônus a seguir (não faz parte do artigo original da VLDB).
Figura bônus: opções de interoperabilidade do ClickBench.
6 DESEMPENHO COMO RECURSO
6.1 Ferramentas integradas de análise de desempenho
6.2 Benchmarks
6.2.1 Tabelas desnormalizadas

Figura 10: Tempos de execução relativos a frio e com cache aquecido do ClickBench.

Figura 11: tempos de execução relativos com cache aquecido do VersionsBench 2018-2024.
6.2.2 Tabelas normalizadas

Figura 12: Tempos de execução com cache aquecido (em segundos) para consultas TPC-H.
8 CONCLUSÃO E PERSPECTIVAS
AGRADECIMENTOS
REFERÊNCIAS
- 1 Daniel Abadi, Peter Boncz, Stavros Harizopoulos, Stratos Idreaos e Samuel Madden. 2013. The Design and Implementation of Modern Column-Oriented Database Systems. https://doi.org/10.1561/9781601987556
- 2 Daniel Abadi, Samuel Madden e Miguel Ferreira. 2006. Integrating Compression and Execution in Column-Oriented Database Systems. Nos anais da 2006 ACM SIGMOD International Conference on Management of Data (SIGMOD ‘06). 671–682.https://doi.org/10.1145/1142473.1142548
- 3 Anastassia Ailamaki, David J. DeWitt, Mark D. Hill e Marios Skounakis. 2001. Weaving Relations for Cache Performance. Nos anais da 27ª International Conference on Very Large Data Bases (VLDB ‘01). Morgan Kaufmann Publishers Inc., San Francisco, CA, USA, 169–180.
- 4 Nikos Armenatzoglou, Sanuj Basu, Naga Bhanoori, Mengchu Cai, Naresh Chainani, Kiran Chinta, Venkatraman Govindaraju, Todd J. Green, Monish Gupta, Sebastian Hillig, Eric Hotinger, Yan Leshinksy, Jintian Liang, Michael McCreedy, Fabian Nagel, Ippokratis Pandis, Panos Parchas, Rahul Pathak, Orestis Polychroniou, Foyzur Rahman, Gaurav Saxena, Gokul Soundararajan, Sriram Subramanian e Doug Terry. 2022. Amazon Redshift Re-Invented. Em anais da 2022 International Conference on Management of Data (Philadelphia, PA, EUA) (SIGMOD ‘22). Association for Computing Machinery, New York, NY, EUA, 2205–2217. https://doi.org/10.1145/3514221.3526045
- 5 Alexander Behm, Shoumik Palkar, Utkarsh Agarwal, Timothy Armstrong, David Cashman, Ankur Dave, Todd Greenstein, Shant Hovsepian, Ryan Johnson, Arvind Sai Krishnan, Paul Leventis, Ala Luszczak, Prashanth Menon, Mostafa Mokhtar, Gene Pang, Sameer Paranjpye, Greg Rahn, Bart Samwel, Tom van Bussel, Herman van Hovell, Maryann Xue, Reynold Xin e Matei Zaharia. 2022. Photon: A Fast Query Engine for Lakehouse Systems (SIGMOD ‘22). Association for Computing Machinery, New York, NY, USA, 2326–2339. https://doi.org/10.1145/3514221. 3526054
- 6 Philip A. Bernstein and Nathan Goodman. 1981. Concurrency Control in Distributed Database Systems. ACM Computing Survey 13, 2 (1981), 185–221. https://doi.org/10.1145/356842.356846
- 7 Spyros Blanas, Yinan Li e Jignesh M. Patel. 2011. Projeto e avaliação de algoritmos de hash join em memória principal para CPUs multicore. In Proceedings of the 2011 ACM SIGMOD International Conference on Management of Data (Athens, Greece) (SIGMOD ‘11). Association for Computing Machinery, New York, NY, USA, 37–48. https://doi.org/10.1145/1989323.1989328
- 8 Daniel Gomez Blanco. 2023. Practical OpenTelemetry. Springer Nature.
- 9 Burton H. Bloom. 1970. Space/Time Trade-Ofs in Hash Coding with Allowable Errors. Commun. ACM 13, 7 (1970), 422–426. https://doi.org/10.1145/362686. 362692
- 10 Peter Boncz, Thomas Neumann, and Orri Erling. 2014. TPC-H Analyzed: Hidden Messages and Lessons Learned from an Infuential Benchmark. In Performance Characterization and Benchmarking. 61–76. https://doi.org/10.1007/978-3-319- 04936-6_5
- 11 Peter Boncz, Marcin Zukowski e Niels Nes. 2005. MonetDB/X100: Hyper-Pipelining Query Execution. Em CIDR.
- 12 Martin Burtscher e Paruj Ratanaworabhan. 2007. High Throughput Compression of Double-Precision Floating-Point Data. Na Data Compression Conference (DCC). 293–302. https://doi.org/10.1109/DCC.2007.44
- 13 Jef Carpenter e Eben Hewitt. 2016. Cassandra: The Defnitive Guide (2ª ed.). O’Reilly Media, Inc.
- 14 Bernadette Charron-Bost, Fernando Pedone e André Schiper (Orgs.). 2010. Replication: Theory and Practice. Springer-Verlag.
- 15 chDB. 2024. chDB - um mecanismo SQL OLAP embutido. Recuperado em 2024-06-20 de https://github.com/chdb-io/chdb
- 16 ClickHouse. 2024. ClickBench: um benchmark para bancos de dados analíticos. Acessado em 2024-06-20 de https://github.com/ClickHouse/ClickBench
- 17 ClickHouse. 2024. ClickBench: Comparative Measurements. Recuperado em 2024-06-20 de https://benchmark.clickhouse.com
- 18 ClickHouse. 2024. Roadmap do ClickHouse 2024 (GitHub). Acessado em 2024-06-20 em https://github.com/ClickHouse/ClickHouse/issues/58392
- 19 ClickHouse. 2024. Benchmark de versões do ClickHouse. Obtido em 2024-06-20 em https://github.com/ClickHouse/ClickBench/tree/main/versions
- 20 ClickHouse. 2024. Resultados do benchmark de versões do ClickHouse. Acesso em 2024-06-20 em https://benchmark.clickhouse.com/versions/
- 21 Andrew Crotty. 2022. MgBench. Obtido em 2024-06-20 de https://github.com/ andrewcrotty/mgbench
- 22 Benoit Dageville, Thierry Cruanes, Marcin Zukowski, Vadim Antonov, Artin Avanes, Jon Bock, Jonathan Claybaugh, Daniel Engovatov, Martin Hentschel, Jiansheng Huang, Allison W. Lee, Ashish Motivala, Abdul Q. Munir, Steven Pelley, Peter Povinec, Greg Rahn, Spyridon Triantafyllis e Philipp Unterbrunner. 2016. The Snowfake Elastic Data Warehouse. In Proceedings of the 2016 International Conference on Management of Data (San Francisco, California, USA) (SIGMOD ‘16). Association for Computing Machinery, New York, NY, USA, 215–226. https: //doi.org/10.1145/2882903.2903741
- 23 Patrick Damme, Annett Ungethüm, Juliana Hildebrandt, Dirk Habich e Wolfgang Lehner. 2019. From a Comprehensive Experimental Survey to a Cost-Based Selection Strategy for Lightweight Integer Compression Algorithms. ACM Trans. Database Syst. 44, 3, Artigo 9 (2019), 46 páginas. https://doi.org/10.1145/3323991
- 24 Philippe Dobbelaere e Kyumars Sheykh Esmaili. 2017. Kafka versus RabbitMQ: um estudo comparativo de duas implementações de publicação/assinatura de referência do setor: artigo industrial (DEBS ‘17). Association for Computing Machinery, New York, NY, USA, 227–238. https://doi.org/10.1145/3093742.3093908
- 25 Documentação do LLVM. 2024. Auto-Vectorization in LLVM. Acessado em 2024-06-20 em https://llvm.org/docs/Vectorizers.html
- 26 Siying Dong, Andrew Kryczka, Yanqin Jin e Michael Stumm. 2021. RocksDB: Evolução das prioridades de desenvolvimento em um armazenamento chave-valor que atende aplicações em larga escala. ACM Transactions on Storage 17, 4, Artigo 26 (2021), 32 páginas. https://doi.org/10.1145/3483840
- 27 Markus Dreseler, Martin Boissier, Tilmann Rabl e Matthias Ufacker. 2020. Quantificando os pontos de estrangulamento do TPC-H e suas otimizações. Proc. VLDB Endow. 13, 8 (2020), 1206–1220. https://doi.org/10.14778/3389133.3389138
- 28 Ted Dunning. 2021. O t-digest: estimativas eficientes para distribuições. Software Impacts 7 (2021). https://doi.org/10.1016/j.simpa.2020.100049
- 29 Martin Faust, Martin Boissier, Marvin Keller, David Schwalb, Holger Bischof, Katrin Eisenreich, Franz Färber e Hasso Plattner. 2016. Footprint Reduction and Uniqueness Enforcement with Hash Indices in SAP HANA. Em Database and Expert Systems Applications. 137–151. https://doi.org/10.1007/978-3-319-44406- 2_11
- 30 Philippe Flajolet, Eric Fusy, Olivier Gandouet e Frederic Meunier. 2007. HyperLogLog: a análise de um algoritmo de estimativa de cardinalidade quase ótimo. Em AofA: Analysis of Algorithms, Vol. DMTCS Proceedings vol. AH, 2007 Conference on Analysis of Algorithms (AofA 07). Discrete Mathematics and Theoretical Computer Science, 137–156. https://doi.org/10.46298/dmtcs.3545
- 31 Hector Garcia-Molina, Jefrey D. Ullman e Jennifer Widom. 2009. Database Systems - The Complete Book (2. ed.).
- 32 Pawan Goyal, Harrick M. Vin e Haichen Chen. 1996. Start-time fair queueing: a scheduling algorithm for integrated services packet switching networks. 26, 4 (1996), 157–168. https://doi.org/10.1145/248157.248171
- 33 Goetz Graefe. 1993. Query Evaluation Techniques for Large Databases. ACM Comput. Surv. 25, 2 (1993), 73–169. https://doi.org/10.1145/152610.152611
- 34 Jean-François Im, Kishore Gopalakrishna, Subbu Subramaniam, Mayank Shrivastava, Adwait Tumbde, Xiaotian Jiang, Jennifer Dai, Seunghyun Lee, Neha Pawar, Jialiang Li e Ravi Aringunram. 2018. Pinot: OLAP em tempo real para 530 milhões de usuários. In Proceedings of the 2018 International Conference on Management of Data (Houston, TX, USA) (SIGMOD ‘18). Association for Computing Machinery, New York, NY, USA, 583–594. https://doi.org/10.1145/3183713.3190661
- 35 ISO/IEC 9075-9:2001 2001. Tecnologia da informação — Linguagem de banco de dados — SQL — Parte 9: Gerenciamento de dados externos (SQL/MED). Norma. International Organization for Standardization.
- 36 Paras Jain, Peter Kraft, Conor Power, Tathagata Das, Ion Stoica e Matei Zaharia. 2023. Analyzing and Comparing Lakehouse Storage Systems. CIDR.
- 37 Project Jupyter. 2024. Jupyter Notebooks. Acessado em 2024-06-20 em https: //jupyter.org/
- 38 Timo Kersten, Viktor Leis, Alfons Kemper, Thomas Neumann, Andrew Pavlo e Peter Boncz. 2018. Everything You Always Wanted to Know about Compiled and Vectorized Queries but Were Afraid to Ask. Proc. VLDB Endow. 11, 13 (set. 2018), 2209–2222. https://doi.org/10.14778/3275366.3284966
- 39 Changkyu Kim, Jatin Chhugani, Nadathur Satish, Eric Sedlar, Anthony D. Nguyen, Tim Kaldewey, Victor W. Lee, Scott A. Brandt e Pradeep Dubey. 2010. FAST: fast architecture sensitive tree search on modern CPUs and GPUs. Nos anais da 2010 ACM SIGMOD International Conference on Management of Data (Indianapolis, Indiana, USA) (SIGMOD ‘10). Association for Computing Machinery, New York, NY, USA, 339–350. https://doi.org/10.1145/1807167.1807206
- 40 Donald E. Knuth. 1973. The Art of Computer Programming, Volume III: Sorting and Searching. Addison-Wesley.
- 41 André Kohn, Viktor Leis, e Thomas Neumann. 2018. Adaptive Execution of Compiled Queries. Em 2018 IEEE 34th International Conference on Data Engineering (ICDE). 197–208. https://doi.org/10.1109/ICDE.2018.00027
- 42 Andrew Lamb, Matt Fuller, Ramakrishna Varadarajan, Nga Tran, Ben Vandiver, Lyric Doshi e Chuck Bear. 2012. The Vertica Analytic Database: C-Store 7 Years Later. Proc. VLDB Endow. 5, 12 (aug 2012), 1790–1801. https://doi.org/10. 14778/2367502.2367518
- 43 Harald Lang, Tobias Mühlbauer, Florian Funke, Peter A. Boncz, Thomas Neumann e Alfons Kemper. 2016. Data Blocks: Hybrid OLTP and OLAP on Compressed Storage using both Vectorization and Compilation. In Proceedings of the 2016 International Conference on Management of Data (San Francisco, California, USA) (SIGMOD ‘16). Association for Computing Machinery, New York, NY, USA, 311–326. https://doi.org/10.1145/2882903.2882925
- 44 Viktor Leis, Peter Boncz, Alfons Kemper e Thomas Neumann. 2014. Morseldriven parallelism: a NUMA-aware query evaluation framework for the manycore age. In Proceedings of the 2014 ACM SIGMOD International Conference on Management of Data (Snowbird, Utah, USA) (SIGMOD ‘14). Association for Computing Machinery, New York, NY, USA, 743–754. https://doi.org/10.1145/2588555. 2610507
- 45 Viktor Leis, Alfons Kemper e Thomas Neumann. 2013. A árvore radix adaptativa: indexação ARTful para bancos de dados em memória. Em 2013 IEEE 29th International Conference on Data Engineering (ICDE). 38–49. https://doi.org/10.1109/ICDE. 2013.6544812
- 46 Chunwei Liu, Anna Pavlenko, Matteo Interlandi e Brandon Haynes. 2023. Uma análise aprofundada sobre formatos abertos comuns para SGBDs analíticos. 16, 11 (jul 2023), 3044–3056. https://doi.org/10.14778/3611479.3611507
- 47 Zhenghua Lyu, Huan Hubert Zhang, Gang Xiong, Gang Guo, Haozhou Wang, Jinbao Chen, Asim Praveen, Yu Yang, Xiaoming Gao, Alexandra Wang, Wen Lin, Ashwin Agrawal, Junfeng Yang, Hao Wu, Xiaoliang Li, Feng Guo, Jiang Wu, Jesse Zhang, e Venkatesh Raghavan. 2021. Greenplum: um banco de dados híbrido para cargas de trabalho transacionais e analíticas (SIGMOD ‘21). Association for Computing Machinery, New York, NY, USA, 2530–2542. https: //doi.org/10.1145/3448016.3457562
- 48 Roger MacNicol e Blaine French. 2004. Sybase IQ Multiplex - Projetado para análise. Nos Anais da Trigésima Conferência Internacional sobre Bancos de Dados Muito Grandes - Volume 30 (Toronto, Canadá) (VLDB ‘04). VLDB Endowment, 1227–1230.
- 49 Sergey Melnik, Andrey Gubarev, Jing Jing Long, Geofrey Romer, Shiva Shivakumar, Matt Tolton, Theo Vassilakis, Hossein Ahmadi, Dan Delorey, Slava Min, Mosha Pasumansky e Jef Shute. 2020. Dremel: A Decade of Interactive SQL Analysis at Web Scale. Proc. VLDB Endow. 13, 12 (aug 2020), 3461–3472. https://doi.org/10.14778/3415478.3415568
- 50 Microsoft. 2024. Kusto Query Language. Recuperado em 2024-06-20 de https: //github.com/microsoft/Kusto-Query-Language
- 51 Guido Moerkotte. 1998. Pequenos agregados materializados: uma estrutura leve de índice para armazenamento de dados. Em Anais da 24ª Conferência Internacional sobre Bancos de Dados Muito Grandes (VLDB ‘98). 476–487.
- 52 Jalal Mostafa, Sara Wehbi, Suren Chilingaryan e Andreas Kopmann. 2022. SciTS: A Benchmark for Time-Series Databases in Scientifc Experiments and Industrial Internet of Things. Nos anais da 34th International Conference on Scientifc and Statistical Database Management (SSDBM ‘22). Artigo 12. https: //doi.org/10.1145/3538712.3538723
- 53 Thomas Neumann. 2011. Compilando planos de consulta com eficiência para hardware moderno. Proc. VLDB Endow. 4, 9 (jun 2011), 539–550. https://doi.org/10.14778/ 2002938.2002940
- 54 Thomas Neumann e Michael J. Freitag. 2020. Umbra: um sistema baseado em disco com desempenho em memória. In: 10th Conference on Innovative Data Systems Research, CIDR 2020, Amsterdam, Holanda, 12 a 15 de janeiro de 2020, anais online. www.cidrdb.org. http://cidrdb.org/cidr2020/papers/p29-neumanncidr20.pdf
- 55 Thomas Neumann, Tobias Mühlbauer e Alfons Kemper. 2015. Controle de Concorrência Multi-Versão Serializável Rápido para Sistemas de Bancos de Dados em Memória Principal. In Anais da Conferência Internacional ACM SIGMOD de 2015 sobre Gerenciamento de Dados (Melbourne, Victoria, Austrália) (SIGMOD ‘15). Association for Computing Machinery, New York, NY, EUA, 677–689. https://doi.org/10.1145/2723372. 2749436
- 56 LevelDB no GitHub. 2024. LevelDB. Acessado em 2024-06-20 em https://github. com/google/leveldb
- 57 Patrick O’Neil, Elizabeth O’Neil, Xuedong Chen e Stephen Revilak. 2009. The Star Schema Benchmark and Augmented Fact Table Indexing. In: Performance Evaluation and Benchmarking. Springer Berlin Heidelberg, 237–252. https: //doi.org/10.1007/978-3-642-10424-4_17
- 58 Patrick E. O’Neil, Edward Y. C. Cheng, Dieter Gawlick, e Elizabeth J. O’Neil. 1996. The log-structured Merge-Tree (LSM-tree). Acta Informatica 33 (1996), 351–385. https://doi.org/10.1007/s002360050048
- 59 Diego Ongaro e John Ousterhout. 2014. Em busca de um algoritmo de consenso compreensível. Nos Anais da Conferência Técnica Anual da USENIX de 2014 (USENIX ATC’14). 305–320. https://doi.org/doi/10. 5555/2643634.2643666
- 60 Patrick O’Neil, Edward Cheng, Dieter Gawlick e Elizabeth O’Neil. 1996. The Log-Structured Merge-Tree (LSM-Tree). Acta Inf. 33, 4 (1996), 351–385. https: //doi.org/10.1007/s002360050048
- 61 Pandas. 2024. DataFrames do Pandas. Recuperado em 2024-06-20 de https://pandas. pydata.org/
- 62 Pedro Pedreira, Orri Erling, Masha Basmanova, Kevin Wilfong, Laith Sakka, Krishna Pai, Wei He, e Biswapesh Chattopadhyay. 2022. Velox: Meta’s Unified Execution Engine. Proc. VLDB Endow. 15, 12 (ago 2022), 3372–3384. https: //doi.org/10.14778/3554821.3554829
- 63 Tuomas Pelkonen, Scott Franklin, Justin Teller, Paul Cavallaro, Qi Huang, Justin Meza e Kaushik Veeraraghavan. 2015. Gorilla: A Fast, Scalable, in-Memory Time Series Database. Proceedings of the VLDB Endowment 8, 12 (2015), 1816–1827. https://doi.org/10.14778/2824032.2824078
- 64 Orestis Polychroniou, Arun Raghavan e Kenneth A. Ross. 2015. Rethinking SIMD Vectorization for In-Memory Databases. Nos Anais da 2015 ACM SIGMOD International Conference on Management of Data (SIGMOD ‘15). 1493–1508. https://doi.org/10.1145/2723372.2747645
- 65 PostgreSQL. 2024. PostgreSQL - Foreign Data Wrappers. Acesso em 2024-06-20 em https://wiki.postgresql.org/wiki/Foreign_data_wrappers
- 66 Mark Raasveldt, Pedro Holanda, Tim Gubner e Hannes Mühleisen. 2018. Fair Benchmarking Considered difficult: Common Pitfalls In Database Performance Testing. Nos anais do Workshop on Testing Database Systems (Houston, TX, USA) (DBTest’18). Artigo 2, 6 páginas. https://doi.org/10.1145/3209950.3209955
- 67 Mark Raasveldt e Hannes Mühleisen. 2019. DuckDB: An Embeddable Analytical Database (SIGMOD ‘19). Association for Computing Machinery, New York, NY, EUA, 1981–1984. https://doi.org/10.1145/3299869.3320212
- 68 Jun Rao and Kenneth A. Ross. 1999. Cache Conscious Indexing for Decision-Support in Main Memory. In Proceedings of the 25th International Conference on Very Large Data Bases (VLDB ‘99). San Francisco, CA, USA, 78–89.
- 69 Navin C. Sabharwal and Piyush Kant Pandey. 2020. Working with Prometheus Query Language (PromQL). In Monitoring Microservices and Containerized Applications. https://doi.org/10.1007/978-1-4842-6216-0_5
- 70 Todd W. Schneider. 2022. Dados de Táxis e Veículos de Aluguel da Cidade de Nova York. Recuperado em 2024-06-20 de https://github.com/toddwschneider/nyc-taxi-data
- 71 Mike Stonebraker, Daniel J. Abadi, Adam Batkin, Xuedong Chen, Mitch Cherniack, Miguel Ferreira, Edmond Lau, Amerson Lin, Sam Madden, Elizabeth O’Neil, Pat O’Neil, Alex Rasin, Nga Tran, e Stan Zdonik. 2005. C-Store: A Column-Oriented DBMS. In Proceedings of the 31st International Conference on Very Large Data Bases (VLDB ‘05). 553–564.
- 72 Teradata. 2024. Teradata Database. Acessado em 2024-06-20 em https://www. teradata.com/resources/datasheets/teradata-database
- 73 Frederik Transier. 2010. Algorithms and Data Structures for In-Memory Text Search Engines. Tese de doutorado. https://doi.org/10.5445/IR/1000015824
- 74 Adrian Vogelsgesang, Michael Haubenschild, Jan Finis, Alfons Kemper, Viktor Leis, Tobias Muehlbauer, Thomas Neumann e Manuel Then. 2018. Get Real: How Benchmarks Fail to Represent the Real World. In Proceedings of the Workshop on Testing Database Systems (Houston, TX, USA) (DBTest’18). Artigo 1, 6 páginas. https://doi.org/10.1145/3209950.3209952
- 75 Site do LZ4. 2024. LZ4. Acesso em 2024-06-20 em https://lz4.org/
- 76 Site do PRQL. 2024. PRQL. Acessado em 2024-06-20 em https://prql-lang.org 77 Till Westmann, Donald Kossmann, Sven Helmer, and Guido Moerkotte. 2000. The Implementation and Performance of Compressed Databases. SIGMOD Rec.
- 29, 3 (set 2000), 55–67. https://doi.org/10.1145/362084.362137 78 Fangjin Yang, Eric Tschetter, Xavier Léauté, Nelson Ray, Gian Merlino e Deep Ganguli. 2014. Druid: A Real-Time Analytical Data Store. In Proceedings of the 2014 ACM SIGMOD International Conference on Management of Data (Snowbird, Utah, USA) (SIGMOD ‘14). Association for Computing Machinery, New York, NY, USA, 157–168. https://doi.org/10.1145/2588555.2595631
- 79 Tianqi Zheng, Zhibin Zhang e Xueqi Cheng. 2020. SAHA: A String Adaptive Hash Table for Analytical Databases. Applied Sciences 10, 6 (2020). https: //doi.org/10.3390/app10061915
- 80 Jingren Zhou and Kenneth A. Ross. 2002. Implementando operações de banco de dados usando instruções SIMD. In Anais da Conferência Internacional ACM SIGMOD de 2002 sobre Gerenciamento de Dados (SIGMOD ‘02). 145–156. https://doi.org/10. 1145/564691.564709
- 81 Marcin Zukowski, Sandor Heman, Niels Nes, e Peter Boncz. 2006. Super-Scalar RAM-CPU Cache Compression. In Proceedings of the 22nd International Conference on Data Engineering (ICDE ‘06). 59. https://doi.org/10.1109/ICDE. 2006.150