Skip to main content

Visão geral

Mapbox Vector Tiles (MVT) são tiles codificados em protobuf que clientes de mapas web, como MapLibre e Mapbox GL, renderizam nativamente. O ClickHouse pode construir esses tiles inteiramente em SQL com um par de funções que trabalham em conjunto:
  • MVTEncodeGeom — uma função escalar que projeta uma geometria no espaço de pixels local de um tile de slippy map e a recorta aos limites do tile.
  • MVTEncode — uma função de agregação que reúne as geometrias projetadas de um grupo nos bytes binários de um tile de camada única.
Duas funções auxiliares, MVTBoundingBox e MVTBoundingBoxMercator, retornam a caixa delimitadora de um tile para que as linhas possam ser restritas a ela na cláusula WHERE usando um índice. Há suporte para geometrias de ponto, linha e polígono, incluindo o tipo Geometry e os tipos geo concretos (Point, LineString, MultiLineString, Ring, Polygon, MultiPolygon). Os bytes resultantes formam um tile completo que pode ser retornado diretamente pela interface HTTP com FORMAT RawBLOB. Essas funções seguem o fluxo de trabalho do PostGIS e também estão disponíveis com seus nomes do PostGIS como aliases: ST_AsMVTGeom para MVTEncodeGeom e ST_AsMVT para MVTEncode.

MVTEncodeGeom

Projeta uma geometria fornecida em coordenadas geográficas (longitude/latitude) para o espaço de pixels local do tile do slippy-map identificado por zoom, tile_x e tile_y, recorta-a aos limites do tile, ajusta-a à grade de pixels inteiros e retorna a geometria no espaço do tile. A projeção é Web Mercator em toda a faixa de coordenadas UInt32. As coordenadas retornadas têm origem no canto superior esquerdo do tile, com o eixo y apontando para baixo, que é a convenção de coordenadas do formato Mapbox Vector Tile, de modo que o resultado pode ser usado diretamente em MVTEncode. As coordenadas são arredondadas para pixels inteiros, portanto agrupar por MVTEncodeGeom consolida as geometrias que caem na mesma grade em um único cluster. Quando clip está habilitado (o padrão), a geometria é recortada ao tile expandido em buffer pixels (o intervalo [-buffer, extent + buffer] em cada eixo); geometrias que caem totalmente fora se tornam NULL. Este é o equivalente ao PostGIS ST_AsMVTGeom. O tipo da geometria de saída depende da entrada: um Point retorna um Point; um LineString ou MultiLineString retorna uma MultiLineString; um Ring, Polygon ou MultiPolygon retorna uma MultiPolygon (o recorte pode dividir uma geometria em várias partes). Sintaxe
Argumentos
  • geometry — Geometria em graus de longitude/latitude. A longitude é limitada a [-180, 180] e a latitude ao intervalo do Web Mercator [-85.05112878, 85.05112878]. Point / LineString / MultiLineString / Ring / Polygon / MultiPolygon / Geometry.
  • zoom — Nível de zoom do mapa Slippy, no intervalo [0, 32]. UInt8.
  • tile_x — Índice da coluna do tile, no intervalo [0, 2^zoom - 1]. UInt32.
  • tile_y — Índice da linha do tile, no intervalo [0, 2^zoom - 1]. UInt32.
  • extent — Extensão opcional do tile em pixels por lado, no intervalo [1, 2147483647]. O padrão é 4096, valor padrão do Mapbox Vector Tile. UInt32.
  • buffer — Buffer de recorte opcional em pixels, no intervalo [0, 2147483647]. O padrão é 1. UInt32.
  • clip — flag opcional; quando diferente de zero (o padrão), a geometria é recortada ao tile mais o buffer. UInt8.
Valor retornado Retorna a geometria no espaço do tile ou NULL se ela for totalmente excluída pelo recorte. Geometry. Exemplo

MVTEncode

Codifica um grupo de feições em uma camada binária do Mapbox Vector Tile. Esta é a contraparte agregada da função escalar MVTEncodeGeom. Cada linha de entrada se torna uma feição; há suporte para geometrias de ponto, linha e polígono. O argumento geometry é um Geometry de coordenadas no espaço do tile, normalmente produzido por MVTEncodeGeom. Linhas cuja geometria é NULL (por exemplo, recortadas por MVTEncodeGeom) são ignoradas. O argumento opcional properties é uma tupla nomeada cujos nomes dos elementos se tornam as chaves de atributo da feição e cujos tipos dos elementos determinam os tipos de valor do tile vetorial. O resultado são os bytes brutos de um tile de camada única. Um grupo vazio produz um tile vazio. Este é o análogo de PostGIS ST_AsMVT. Sintaxe
Parâmetros
  • layer_name — Nome da camada do tile vetorial. String.
  • extent — Extensão do tile, em pixels por lado, no intervalo [1, 2147483647]. O padrão é 4096. UInt32.
  • feature_id_name — Nome opcional de um elemento inteiro sem sinal da tupla properties, emitido como o id da feição MVT (um UInt64) em vez de como um atributo. Inteiros com sinal são rejeitados. Um id NULL é omitido para essa feição. Os parâmetros são posicionais; portanto, para usar feature_id_name, é preciso informar extent. String.
  • stringify_unsupported — flag opcional (0/1, padrão 0); quando 1, tipos de propriedade sem suporte direto (por exemplo, inteiros grandes, UUID, Decimal) são codificados como string_value textual em vez de gerar um erro. UInt8.
Argumentos
  • geometry — Geometria no espaço do tile, por exemplo, gerada por MVTEncodeGeom. Geometry.
  • properties — Tupla nomeada opcional de atributos da feição. Os nomes dos elementos se tornam chaves de atributo. Tuple.
Valor retornado Retorna o conteúdo binário de um Mapbox Vector Tile com uma única camada. String.

Tipos de propriedade

Cada elemento de propriedade é codificado como a variante Value do Mapbox Vector Tile correspondente ao seu tipo no ClickHouse: Os tipos podem ser encapsulados em Nullable e/ou LowCardinality. Um valor NULL omite esse atributo da feição, pois o formato tile vetorial não tem valor nulo. Qualquer outro tipo de propriedade gera uma exceção, a menos que stringify_unsupported esteja definido, caso em que ele é codificado como string_value textual. Valores de propriedade idênticos são internados no pool compartilhado de valores da camada, de modo que um valor que aparece em muitas feições é armazenado apenas uma vez.

Nomeando a tupla de propriedades

A tupla de propriedades deve ter nomes de elementos explícitos. Os aliases de coluna dentro de tuple(...) não são propagados para os nomes dos elementos da tupla, portanto nomeie os elementos com um CAST:

Agrupamento

O agrupamento é expresso em SQL, não pela função. Como MVTEncodeGeom arredonda para pixels inteiros, agrupar pela geometria do pixel mescla geometrias coincidentes; agregue o grupo em uma subconsulta e, em seguida, passe uma linha por agrupamento para MVTEncode:
Agrupar por um valor Geometry exige allow_suspicious_types_in_group_by = 1, porque o agrupamento pelo tipo Geometry baseado em Variant é restringido por padrão. Omita o GROUP BY interno (e count()) para gerar uma feição por linha de entrada em vez de feições agrupadas.

MVTBoundingBox

Retorna a caixa delimitadora geográfica do tile slippy-map identificado por zoom, tile_x e tile_y como uma tupla (min_lon, min_lat, max_lon, max_lat) em graus. Use-a para restringir linhas a um tile enquanto filtra diretamente pelas colunas longitude/latitude — assim, uma chave primária ou índice nessas colunas pode ser usado — em vez de recalcular a projeção Web Mercator para cada linha. A margin opcional expande a caixa em todos os lados por essa fração do tamanho do tile; defina-a como buffer / extent para cobrir o buffer de recorte de MVTEncodeGeom. Sintaxe
Argumentos
  • zoom — Nível de zoom do mapa Slippy, no intervalo [0, 32]. UInt8.
  • tile_x — Índice da coluna do tile, no intervalo [0, 2^zoom - 1]. UInt32.
  • tile_y — Índice da linha do tile, no intervalo [0, 2^zoom - 1]. UInt32.
  • margin — Fração opcional do tamanho do tile usada para expandir a caixa em todos os lados. O padrão é 0. Float64.
Valor retornado Retorna a caixa delimitadora do tile como uma tupla (min_lon, min_lat, max_lon, max_lat) em graus. Tuple(Float64, Float64, Float64, Float64). Exemplo

MVTBoundingBoxMercator

A contraparte em Web Mercator de MVTBoundingBox. Retorna a caixa delimitadora do tile no espaço completo de coordenadas Web Mercator em UInt32, usado internamente por MVTEncodeGeom, como uma tupla (min_x, min_y, max_x, max_y). O eixo y cresce para baixo (norte na parte superior). Destina-se a tabelas que materializam colunas de coordenadas Mercator e criam índices sobre elas, em vez de longitude/latitude. Sintaxe
Argumentos Igual a MVTBoundingBox. Valor retornado Retorna a caixa delimitadora do tile como uma tupla (min_x, min_y, max_x, max_y) em coordenadas Web Mercator. Tuple(Float64, Float64, Float64, Float64). Exemplo

Restringindo linhas a um tile

Um tile deve conter apenas a geometria que pertence a ele. Isso é expresso da melhor forma em duas etapas complementares: um predicado barato de caixa delimitadora, que usa índice, na cláusula WHERE (desempenho), e o recorte feito por MVTEncodeGeom (correção). O recorte descarta a geometria fora do tile; assim, mesmo um predicado de caixa delimitadora pouco restritivo não deixa vazar geometria de fora do tile para o resultado.
O predicado de caixa delimitadora é apenas um pré-filtro aproximado; o limite exato do tile é determinado pelo recorte de MVTEncodeGeom. Passe clip => false (o sétimo argumento) para MVTEncodeGeom para desativar o recorte e depender apenas do predicado WHERE.

Disponibilizando tiles via HTTP

O ClickHouse não expõe um endpoint de tile por padrão: a interface HTTP só aceita consultas em /. Uma URL limpa /tile/{z}/{x}/{y} é adicionada pelo operador com um handler de consulta predefinida na configuração do servidor. A url do handler usa a forma regex: para capturar os segmentos do caminho, associá-los aos parâmetros da consulta e retornar os bytes com FORMAT RawBLOB. No caso mais simples, a tabela tem uma coluna Geometry e o handler retorna uma feição por linha — MVTEncodeGeom projeta cada geometria no tile solicitado e a recorta, de modo que as linhas fora do tile são descartadas automaticamente:
Aqui, shapes é uma tabela com uma coluna geom Geometry (qualquer combinação de pontos, linhas e polígonos). Um GET /tile/10/550/335 retorna o tile codificado. Para dados de pontos, isso funciona igualmente bem com colunas simples de longitude/latitude, construindo o ponto diretamente com MVTEncodeGeom((lon, lat)::Point, …). Para agrupar feições coincidentes ou adicionar um pré-filtro de caixa delimitadora com uso de índice em tabelas grandes, estenda a consulta interna como mostrado em Clustering e Restricting rows to a tile.

Limitações

  • A projeção Web Mercator limita a latitude a ±85.05112878° e não lida com entradas que cruzam o antimeridiano.
  • O recorte de polígonos não garante uma saída MVT válida. O recorte corrige a orientação e o fechamento dos anéis, mas não as autointerseções. Portanto, um anel autointersectante (“gravata-borboleta”) não é reparado: dependendo de como ele intersecta o tile, ele é emitido sem alterações (ainda inválido) ou descartado como NULL. Por exemplo, uma gravata-borboleta inteiramente dentro do tile é descartada, enquanto os mesmos quatro cantos, organizados como um anel simples, são mantidos:
  • Geometry é recortada antes de ser arredondada para a grade de pixels inteiros. O PostGIS primeiro ajusta a geometria à grade de pixels inteiros e depois a recorta; MVTEncodeGeom primeiro recorta (nas coordenadas projetadas de ponto flutuante) e depois arredonda. Perto da borda de um tile, isso pode descartar uma coordenada que, de outra forma, seria arredondada para o pixel da borda. Por exemplo, com buffer = 0, um ponto logo a leste da borda do tile é recortado, embora seja arredondado para o pixel da borda 4096, que uma abordagem que arredonda primeiro manteria:
Last modified on June 25, 2026