NumericIndexedVector é uma estrutura de dados abstrata que encapsula um vetor e implementa operações de agregação de vetores e operações ponto a ponto. Bit-Sliced Index é o método de armazenamento usado. Para conhecer a base teórica e os cenários de uso, consulte o artigo Large-Scale Metric Computation in Online Controlled Experiment Platform.
No método de armazenamento BSI (Bit-Sliced Index), os dados são armazenados em Bit-Sliced Index e depois compactados com Roaring Bitmap. As operações de agregação e as operações ponto a ponto são executadas diretamente sobre os dados compactados, o que pode melhorar significativamente a eficiência do armazenamento e da consulta.
Um vetor contém índices e seus valores correspondentes. A seguir estão algumas características e restrições dessa estrutura de dados no modo de armazenamento BSI:
- O tipo de índice pode ser
UInt8, UInt16 ou UInt32. Observação: Considerando o desempenho da implementação de 64 bits do Roaring Bitmap, o formato BSI não oferece suporte a UInt64/Int64.
- O tipo de valor pode ser
Int8, Int16, Int32, Int64, UInt8, UInt16, UInt32, UInt64, Float32 ou Float64. Observação: O tipo de valor não é expandido automaticamente. Por exemplo, se você usar UInt8 como tipo de valor, qualquer soma que exceda a capacidade de UInt8 resultará em overflow, em vez de ser promovida para um tipo maior; da mesma forma, operações com inteiros produzirão resultados inteiros (por exemplo, a divisão não será convertida automaticamente em um resultado de ponto flutuante). Portanto, é importante planejar e definir o tipo de valor antecipadamente. Em cenários reais, tipos de ponto flutuante (Float32/Float64) são comumente usados.
- Somente dois vetores com o mesmo tipo de índice e o mesmo tipo de valor podem realizar operações.
- O armazenamento subjacente usa Bit-Sliced Index, com bitmaps para armazenar índices. O Roaring Bitmap é usado como implementação específica de bitmap. Uma prática recomendada é concentrar os índices em alguns contêineres do Roaring Bitmap tanto quanto possível para maximizar a compactação e o desempenho da consulta.
- O mecanismo Bit-Sliced Index converte o valor em binário. Para tipos de ponto flutuante, a conversão usa representação de ponto fixo, o que pode levar à perda de precisão. A precisão pode ser ajustada personalizando o número de bits usados para a parte fracionária; o padrão é 24 bits, o que é suficiente para a maioria dos cenários. Você pode personalizar o número de bits inteiros e fracionários ao construir NumericIndexedVector usando a função de agregação groupNumericIndexedVector com
-State.
- Há três casos para índices: valor diferente de zero, valor zero e inexistente. Em NumericIndexedVector, somente valores diferentes de zero e valores zero são armazenados. Além disso, em operações ponto a ponto entre dois NumericIndexedVectors, o valor de um índice inexistente será tratado como 0. Em cenários de divisão, o resultado é zero quando o divisor é zero.
Criar um objeto numericIndexedVector
Há duas maneiras de criar essa estrutura: uma é usar a função de agregação groupNumericIndexedVector com -State.
Você pode adicionar o sufixo -if para aceitar uma condição adicional.
A função de agregação processará apenas as linhas que satisfizerem a condição.
A outra é construí-la a partir de um map usando numericIndexedVectorBuild.
A função groupNumericIndexedVectorState permite personalizar o número de bits inteiros e fracionários por meio de parâmetros, enquanto numericIndexedVectorBuild não permite isso.
groupNumericIndexedVector
Cria um NumericIndexedVector a partir de duas colunas de dados e retorna a soma de todos os valores no tipo Float64. Se o sufixo State for adicionado, retorna um objeto NumericIndexedVector.
Sintaxe
groupNumericIndexedVectorState(col1, col2)
groupNumericIndexedVectorState(type, integer_bit_num, fraction_bit_num)(col1, col2)
Parâmetros
type: String, opcional. Especifica o formato de armazenamento. Atualmente, apenas 'BSI' é compatível.
integer_bit_num: UInt32, opcional. Válido no formato de armazenamento 'BSI', este parâmetro indica o número de bits usados para a parte inteira. Quando o tipo do índice é um tipo inteiro, o valor padrão corresponde ao número de bits usados para armazenar o índice. Por exemplo, se o tipo do índice for UInt16, o valor padrão de integer_bit_num será 16. Para tipos de índice Float32 e Float64, o valor padrão de integer_bit_num é 40, portanto a parte inteira dos dados que pode ser representada fica no intervalo [-2^39, 2^39 - 1]. O intervalo válido é [0, 64].
fraction_bit_num: UInt32, opcional. Válido no formato de armazenamento 'BSI', este parâmetro indica o número de bits usados para a parte fracionária. Quando o tipo de valor é inteiro, o valor padrão é 0; quando o tipo de valor é Float32 ou Float64, o valor padrão é 24. O intervalo válido é [0, 24].
- Há também a restrição de que o intervalo válido de integer_bit_num + fraction_bit_num é [0, 64].
col1: A coluna de índice. Tipos compatíveis: UInt8/UInt16/UInt32/Int8/Int16/Int32.
col2: A coluna de valor. Tipos compatíveis: Int8/Int16/Int32/Int64/UInt8/UInt16/UInt32/UInt64/Float32/Float64.
Valor de retorno
Um valor Float64 que representa a soma de todos os valores.
Exemplo
Dados de teste:
UserID PlayTime
1 10
2 20
3 30
Consulta & resultado:
SELECT groupNumericIndexedVector(UserID, PlayTime) AS num FROM t;
┌─num─┐
│ 60 │
└─────┘
SELECT groupNumericIndexedVectorState(UserID, PlayTime) as res, toTypeName(res), numericIndexedVectorAllValueSum(res) FROM t;
┌─res─┬─toTypeName(res)─────────────────────────────────────────────┬─numericIndexedVectorAllValueSum(res)──┐
│ │ AggregateFunction(groupNumericIndexedVector, UInt8, UInt8) │ 60 │
└─────┴─────────────────────────────────────────────────────────────┴───────────────────────────────────────┘
SELECT groupNumericIndexedVectorStateIf(UserID, PlayTime, day = '2025-04-22') as res, toTypeName(res), numericIndexedVectorAllValueSum(res) FROM t;
┌─res─┬─toTypeName(res)────────────────────────────────────────────┬─numericIndexedVectorAllValueSum(res)──┐
│ │ AggregateFunction(groupNumericIndexedVector, UInt8, UInt8) │ 30 │
└─────┴────────────────────────────────────────────────────────────┴───────────────────────────────────────┘
SELECT groupNumericIndexedVectorStateIf('BSI', 32, 0)(UserID, PlayTime, day = '2025-04-22') as res, toTypeName(res), numericIndexedVectorAllValueSum(res) FROM t;
┌─res─┬─toTypeName(res)──────────────────────────────────────────────────────────┬─numericIndexedVectorAllValueSum(res)──┐
│ │ AggregateFunction('BSI', 32, 0)(groupNumericIndexedVector, UInt8, UInt8) │ 30 │
└─────┴──────────────────────────────────────────────────────────────────────────┴───────────────────────────────────────┘
A documentação abaixo é gerada a partir da tabela do sistema system.functions.
numericIndexedVectorAllValueSum
Introduzido em: v25.7.0
Retorna a soma de todos os valores de numericIndexedVector.
Sintaxe
numericIndexedVectorAllValueSum(v)
Argumentos
Valor retornado
Retorna a soma. Float64
Exemplos
Exemplo de uso
SELECT numericIndexedVectorAllValueSum(numericIndexedVectorBuild(mapFromArrays([1, 2, 3], [10, 20, 30]))) AS res;
numericIndexedVectorBuild
Introduzido em: v25.7.0
Cria um NumericIndexedVector a partir de um map. As chaves do map representam os índices do vetor, e os valores do map representam os valores do vetor.
Sintaxe
numericIndexedVectorBuild(map)
Argumentos
map — Um mapeamento de índice para valor. Map
Valor retornado
Retorna um objeto NumericIndexedVector. AggregateFunction
Exemplos
Exemplo de uso
SELECT numericIndexedVectorBuild(mapFromArrays([1, 2, 3], [10, 20, 30])) AS res, toTypeName(res);
┌─res─┬─toTypeName(res)────────────────────────────────────────────┐
│ │ AggregateFunction(groupNumericIndexedVector, UInt8, UInt8) │
└─────┴────────────────────────────────────────────────────────────┘
numericIndexedVectorCardinality
Introduzido em: v25.7.0
Retorna a cardinalidade (número de índices distintos) do numericIndexedVector.
Sintaxe
numericIndexedVectorCardinality(v)
Argumentos
Valor retornado
Retorna o número de índices únicos. UInt64
Exemplos
Exemplo de uso
SELECT numericIndexedVectorCardinality(numericIndexedVectorBuild(mapFromArrays([1, 2, 3], [10, 20, 30]))) AS res;
numericIndexedVectorGetValue
Introduzido em: v25.7.0
Recupera o valor correspondente a um índice especificado em um numericIndexedVector.
Sintaxe
numericIndexedVectorGetValue(v, i)
Argumentos
Valor retornado
Um valor numérico do mesmo tipo que o tipo de valor de NumericIndexedVector. (U)Int* ou Float*
Exemplos
Exemplo de uso
SELECT numericIndexedVectorGetValue(numericIndexedVectorBuild(mapFromArrays([1, 2, 3], [10, 20, 30])), 3) AS res;
numericIndexedVectorPointwiseAdd
Introduzido em: v25.7.0
Realiza a adição ponto a ponto entre um numericIndexedVector e outro numericIndexedVector ou uma constante numérica.
Sintaxe
numericIndexedVectorPointwiseAdd(v1, v2)
Argumentos
Valor retornado
Retorna um novo objeto numericIndexedVector. numericIndexedVector
Exemplos
Exemplo de uso
WITH
numericIndexedVectorBuild(mapFromArrays([1, 2, 3], arrayMap(x -> toInt32(x), [10, 20, 30]))) AS vec1,
numericIndexedVectorBuild(mapFromArrays([2, 3, 4], arrayMap(x -> toInt32(x), [10, 20, 30]))) AS vec2
SELECT
numericIndexedVectorToMap(numericIndexedVectorPointwiseAdd(vec1, vec2)) AS res1,
numericIndexedVectorToMap(numericIndexedVectorPointwiseAdd(vec1, 2)) AS res2;
┌─res1──────────────────┬─res2─────────────┐
│ {1:10,2:30,3:50,4:30} │ {1:12,2:22,3:32} │
└───────────────────────┴──────────────────┘
numericIndexedVectorPointwiseDivide
Introduzido em: v25.7.0
Realiza a divisão ponto a ponto entre um numericIndexedVector e outro numericIndexedVector ou uma constante numérica.
Sintaxe
numericIndexedVectorPointwiseDivide(v1, v2)
Argumentos
Valor retornado
Retorna um novo objeto numericIndexedVector. numericIndexedVector
Exemplos
Exemplo de uso
with
numericIndexedVectorBuild(mapFromArrays([1, 2, 3], arrayMap(x -> toFloat64(x), [10, 20, 30]))) as vec1,
numericIndexedVectorBuild(mapFromArrays([2, 3, 4], arrayMap(x -> toFloat64(x), [10, 20, 30]))) as vec2
SELECT
numericIndexedVectorToMap(numericIndexedVectorPointwiseDivide(vec1, vec2)) AS res1,
numericIndexedVectorToMap(numericIndexedVectorPointwiseDivide(vec1, 2)) AS res2;
┌─res1────────┬─res2────────────┐
│ {2:2,3:1.5} │ {1:5,2:10,3:15} │
└─────────────┴─────────────────┘
numericIndexedVectorPointwiseEqual
Introduzido na versão: v25.7.0
Realiza uma comparação ponto a ponto entre um numericIndexedVector e outro numericIndexedVector ou uma constante numérica.
O resultado é um numericIndexedVector contendo os índices em que os valores são iguais, com todos os valores correspondentes definidos como 1.
Sintaxe
numericIndexedVectorPointwiseEqual(v1, v2)
Argumentos
Valor retornado
Retorna um novo objeto numericIndexedVector. numericIndexedVector
Exemplos
with
numericIndexedVectorBuild(mapFromArrays([1, 2, 3], arrayMap(x -> toFloat64(x), [10, 20, 30]))) as vec1,
numericIndexedVectorBuild(mapFromArrays([2, 3, 4], arrayMap(x -> toFloat64(x), [20, 20, 30]))) as vec2
SELECT
numericIndexedVectorToMap(numericIndexedVectorPointwiseEqual(vec1, vec2)) AS res1,
numericIndexedVectorToMap(numericIndexedVectorPointwiseEqual(vec1, 20)) AS res2;
┌─res1──┬─res2──┐
│ {2:1} │ {2:1} │
└───────┴───────┘
numericIndexedVectorPointwiseGreater
Introduzido em: v25.7.0
Realiza uma comparação ponto a ponto entre um numericIndexedVector e outro numericIndexedVector ou uma constante numérica.
O resultado é um numericIndexedVector contendo os índices em que o valor do primeiro vetor é maior do que o valor do segundo vetor, com todos os valores correspondentes definidos como 1.
Sintaxe
numericIndexedVectorPointwiseGreater(v1, v2)
Argumentos
Valor retornado
Retorna um novo objeto numericIndexedVector. numericIndexedVector
Exemplos
Exemplo de uso
with
numericIndexedVectorBuild(mapFromArrays([1, 2, 3], arrayMap(x -> toFloat64(x), [10, 20, 50]))) as vec1,
numericIndexedVectorBuild(mapFromArrays([2, 3, 4], arrayMap(x -> toFloat64(x), [20, 40, 30]))) as vec2
SELECT
numericIndexedVectorToMap(numericIndexedVectorPointwiseGreater(vec1, vec2)) AS res1,
numericIndexedVectorToMap(numericIndexedVectorPointwiseGreater(vec1, 20)) AS res2;
┌─res1──────┬─res2──┐
│ {1:1,3:1} │ {3:1} │
└───────────┴───────┘
numericIndexedVectorPointwiseGreaterEqual
Introduzido na versão: v25.7.0
Realiza uma comparação ponto a ponto entre um numericIndexedVector e outro numericIndexedVector ou uma constante numérica.
O resultado é um numericIndexedVector que contém os índices em que o valor do primeiro vetor é maior ou igual ao do segundo vetor, com todos os valores correspondentes definidos como 1.
Sintaxe
numericIndexedVectorPointwiseGreaterEqual(v1, v2)
Argumentos
Valor retornado
Retorna um novo objeto numericIndexedVector.
Exemplos
Exemplo de uso
with
numericIndexedVectorBuild(mapFromArrays([1, 2, 3], arrayMap(x -> toFloat64(x), [10, 20, 50]))) as vec1,
numericIndexedVectorBuild(mapFromArrays([2, 3, 4], arrayMap(x -> toFloat64(x), [20, 40, 30]))) as vec2
SELECT
numericIndexedVectorToMap(numericIndexedVectorPointwiseGreaterEqual(vec1, vec2)) AS res1,
numericIndexedVectorToMap(numericIndexedVectorPointwiseGreaterEqual(vec1, 20)) AS res2;
┌─res1──────────┬─res2──────┐
│ {1:1,2:1,3:1} │ {2:1,3:1} │
└───────────────┴───────────┘
numericIndexedVectorPointwiseLess
Introduzido em: v25.7.0
Realiza uma comparação ponto a ponto entre um numericIndexedVector e outro numericIndexedVector ou uma constante numérica.
O resultado é um numericIndexedVector contendo os índices em que o valor do primeiro vetor é menor que o valor do segundo, com todos os valores correspondentes definidos como 1.
Sintaxe
numericIndexedVectorPointwiseLess(v1, v2)
Argumentos
Valor retornado
Retorna um novo objeto numericIndexedVector. numericIndexedVector
Exemplos
Exemplo de uso
with
numericIndexedVectorBuild(mapFromArrays([1, 2, 3], arrayMap(x -> toFloat64(x), [10, 20, 30]))) as vec1,
numericIndexedVectorBuild(mapFromArrays([2, 3, 4], arrayMap(x -> toFloat64(x), [20, 40, 30]))) as vec2
SELECT
numericIndexedVectorToMap(numericIndexedVectorPointwiseLess(vec1, vec2)) AS res1,
numericIndexedVectorToMap(numericIndexedVectorPointwiseLess(vec1, 20)) AS res2;
┌─res1──────┬─res2──┐
│ {3:1,4:1} │ {1:1} │
└───────────┴───────┘
numericIndexedVectorPointwiseLessEqual
Introduzido em: v25.7.0
Realiza uma comparação ponto a ponto entre um numericIndexedVector e outro numericIndexedVector ou uma constante numérica.
O resultado é um numericIndexedVector contendo os índices em que o valor do primeiro vetor é menor ou igual ao do segundo vetor, com todos os valores correspondentes definidos como 1.
Sintaxe
numericIndexedVectorPointwiseLessEqual(v1, v2)
Argumentos
Valor retornado
Retorna um novo objeto numericIndexedVector.
Exemplos
Exemplo de uso
with
numericIndexedVectorBuild(mapFromArrays([1, 2, 3], arrayMap(x -> toFloat64(x), [10, 20, 30]))) as vec1,
numericIndexedVectorBuild(mapFromArrays([2, 3, 4], arrayMap(x -> toFloat64(x), [20, 40, 30]))) as vec2
SELECT
numericIndexedVectorToMap(numericIndexedVectorPointwiseLessEqual(vec1, vec2)) AS res1,
numericIndexedVectorToMap(numericIndexedVectorPointwiseLessEqual(vec1, 20)) AS res2;
┌─res1──────────┬─res2──────┐
│ {2:1,3:1,4:1} │ {1:1,2:1} │
└───────────────┴───────────┘
numericIndexedVectorPointwiseMultiply
Introduzido em: v25.7.0
Realiza a multiplicação ponto a ponto entre um numericIndexedVector e outro numericIndexedVector ou uma constante numérica.
Sintaxe
numericIndexedVectorPointwiseMultiply(v1, v2)
Argumentos
Valor retornado
Retorna um novo objeto numericIndexedVector. numericIndexedVector
Exemplos
with
numericIndexedVectorBuild(mapFromArrays([1, 2, 3], arrayMap(x -> toInt32(x), [10, 20, 30]))) as vec1,
numericIndexedVectorBuild(mapFromArrays([2, 3, 4], arrayMap(x -> toInt32(x), [10, 20, 30]))) as vec2
SELECT
numericIndexedVectorToMap(numericIndexedVectorPointwiseMultiply(vec1, vec2)) AS res1,
numericIndexedVectorToMap(numericIndexedVectorPointwiseMultiply(vec1, 2)) AS res2;
┌─res1──────────┬─res2─────────────┐
│ {2:200,3:600} │ {1:20,2:40,3:60} │
└───────────────┴──────────────────┘
numericIndexedVectorPointwiseNotEqual
Introduzido em: v25.7.0
Realiza uma comparação ponto a ponto entre um numericIndexedVector e outro numericIndexedVector ou uma constante numérica.
O resultado é um numericIndexedVector que contém os índices em que os valores são diferentes, com todos os valores correspondentes definidos como 1.
Sintaxe
numericIndexedVectorPointwiseNotEqual(v1, v2)
Argumentos
Valor retornado
Retorna um novo objeto numericIndexedVector. numericIndexedVector
Exemplos
Exemplo de uso
with
numericIndexedVectorBuild(mapFromArrays([1, 2, 3], arrayMap(x -> toFloat64(x), [10, 20, 30]))) as vec1,
numericIndexedVectorBuild(mapFromArrays([2, 3, 4], arrayMap(x -> toFloat64(x), [20, 20, 30]))) as vec2
SELECT
numericIndexedVectorToMap(numericIndexedVectorPointwiseNotEqual(vec1, vec2)) AS res1,
numericIndexedVectorToMap(numericIndexedVectorPointwiseNotEqual(vec1, 20)) AS res2;
┌─res1──────────┬─res2──────┐
│ {1:1,3:1,4:1} │ {1:1,3:1} │
└───────────────┴───────────┘
numericIndexedVectorPointwiseSubtract
Introduzido em: v25.7.0
Realiza a subtração ponto a ponto entre um numericIndexedVector e outro numericIndexedVector ou uma constante numérica.
Sintaxe
numericIndexedVectorPointwiseSubtract(v1, v2)
Argumentos
Valor retornado
Retorna um novo objeto numericIndexedVector. numericIndexedVector
Exemplos
Exemplo de uso
WITH
numericIndexedVectorBuild(mapFromArrays([1, 2, 3], arrayMap(x -> toInt32(x), [10, 20, 30]))) AS vec1,
numericIndexedVectorBuild(mapFromArrays([2, 3, 4], arrayMap(x -> toInt32(x), [10, 20, 30]))) AS vec2
SELECT
numericIndexedVectorToMap(numericIndexedVectorPointwiseSubtract(vec1, vec2)) AS res1,
numericIndexedVectorToMap(numericIndexedVectorPointwiseSubtract(vec1, 2)) AS res2;
┌─res1───────────────────┬─res2────────────┐
│ {1:10,2:10,3:10,4:-30} │ {1:8,2:18,3:28} │
└────────────────────────┴─────────────────┘
numericIndexedVectorShortDebugString
Introduzido em: v25.7.0
Retorna informações internas do numericIndexedVector em formato JSON.
Esta função é usada principalmente para depuração.
Sintaxe
numericIndexedVectorShortDebugString(v)
Argumentos
Valor retornado
Retorna uma string JSON com informações de depuração. String
Exemplos
Exemplo de uso
SELECT numericIndexedVectorShortDebugString(numericIndexedVectorBuild(mapFromArrays([1, 2, 3], [10, 20, 30]))) AS res\G;
Row 1:
──────
res: {"vector_type":"BSI","index_type":"char8_t","value_type":"char8_t","integer_bit_num":8,"fraction_bit_num":0,"zero_indexes_info":{"cardinality":"0"},"non_zero_indexes_info":{"total_cardinality":"3","all_value_sum":60,"number_of_bitmaps":"8","bitmap_info":{"cardinality":{"0":"0","1":"2","2":"2","3":"2","4":"2","5":"0","6":"0","7":"0"}}}}
numericIndexedVectorToMap
Introduzido na versão: v25.7.0
Converte um numericIndexedVector em um map.
Sintaxe
numericIndexedVectorToMap(v)
Argumentos
Valor retornado
Retorna um map com pares de índice e valor. Map
Exemplos
Exemplo de uso
SELECT numericIndexedVectorToMap(numericIndexedVectorBuild(mapFromArrays([1, 2, 3], [10, 20, 30]))) AS res;
┌─res──────────────┐
│ {1:10,2:20,3:30} │
└──────────────────┘