Перейти к основному содержанию
NumericIndexedVector представляет собой абстрактную структуру данных, которая инкапсулирует вектор и поддерживает агрегирование векторов и покомпонентные операции. Bit-Sliced Index служит методом его хранения. Теоретические основы и сценарии использования см. в статье Large-Scale Metric Computation in Online Controlled Experiment Platform.

BSI

В методе хранения BSI (Bit-Sliced Index) данные сохраняются в Bit-Sliced Index, а затем сжимаются с помощью Roaring Bitmap. Агрегирующие и покомпонентные операции выполняются непосредственно над сжатыми данными, что может значительно повысить эффективность хранения и выполнения запросов. Вектор содержит индексы и соответствующие им значения. Ниже приведены некоторые характеристики и ограничения этой структуры данных в режиме хранения BSI:
  • Тип индекса может быть одним из UInt8, UInt16 или UInt32. Примечание: с учетом производительности 64-битной реализации Roaring Bitmap формат BSI не поддерживает UInt64/Int64.
  • Тип значения может быть одним из Int8, Int16, Int32, Int64, UInt8, UInt16, UInt32, UInt64, Float32 или Float64. Примечание: тип значения не расширяется автоматически. Например, если использовать UInt8 в качестве типа значения, любая сумма, превышающая диапазон UInt8, приведет к переполнению, а не к переходу к более широкому типу; аналогично, операции над целыми числами будут давать целочисленные результаты (например, деление не будет автоматически преобразовано в число с плавающей точкой). Поэтому важно заранее продумать и выбрать тип значения. На практике часто используются типы с плавающей точкой (Float32/Float64).
  • Операции можно выполнять только над двумя векторами с одинаковыми типами индекса и значения.
  • Нижележащее хранилище использует Bit-Sliced Index, при этом индексы хранятся в битмапах. В качестве конкретной реализации битмапа используется Roaring Bitmap. Рекомендуется по возможности концентрировать индексы в нескольких контейнерах Roaring Bitmap, чтобы максимально повысить степень сжатия и производительность запросов.
  • Механизм Bit-Sliced Index преобразует значение в двоичный вид. Для типов с плавающей точкой преобразование использует представление с фиксированной точкой, что может приводить к потере точности. Точность можно настроить, задав число битов, используемых для дробной части; по умолчанию это 24 бита, чего достаточно для большинства сценариев. При создании NumericIndexedVector можно настроить число битов для целой и дробной частей с помощью агрегатной функции groupNumericIndexedVector с -State.
  • Для индексов возможны три состояния: ненулевое значение, нулевое значение и отсутствие. В NumericIndexedVector сохраняются только ненулевые и нулевые значения. Кроме того, в покомпонентных операциях между двумя NumericIndexedVectors значение отсутствующего индекса считается равным 0. В случае деления результат равен нулю, если делитель равен нулю.

Создание объекта numericIndexedVector

Эту структуру можно создать двумя способами: первый — использовать агрегатную функцию groupNumericIndexedVector с -State. Можно добавить суффикс -if, чтобы задать дополнительное условие. Агрегатная функция будет обрабатывать только те строки, которые удовлетворяют этому условию. Второй способ — построить её из Map с помощью numericIndexedVectorBuild. Функция groupNumericIndexedVectorState позволяет настраивать количество битов целой и дробной части с помощью параметров, тогда как numericIndexedVectorBuild такой возможности не предоставляет.

groupNumericIndexedVector

Создаёт NumericIndexedVector из двух столбцов данных и возвращает сумму всех значений типа Float64. Если добавить суффикс State, функция вернёт объект NumericIndexedVector. Синтаксис
groupNumericIndexedVectorState(col1, col2)
groupNumericIndexedVectorState(type, integer_bit_num, fraction_bit_num)(col1, col2)
Параметры
  • type: String, необязательно. Задаёт формат хранения. В настоящее время поддерживается только 'BSI'.
  • integer_bit_num: UInt32, необязательно. Используется только для формата хранения 'BSI'; этот параметр задаёт количество битов, используемых для целой части. Если тип индекса целочисленный, значение по умолчанию соответствует числу битов, используемых для хранения индекса. Например, если тип индекса — UInt16, то значение integer_bit_num по умолчанию равно 16. Для типов индекса Float32 и Float64 значение integer_bit_num по умолчанию равно 40, поэтому целая часть представимых данных находится в диапазоне [-2^39, 2^39 - 1]. Допустимый диапазон — [0, 64].
  • fraction_bit_num: UInt32, необязательно. Используется только для формата хранения 'BSI'; этот параметр задаёт количество битов, используемых для дробной части. Если тип значения целочисленный, значение по умолчанию равно 0; если тип значения — Float32 или Float64, значение по умолчанию равно 24. Допустимый диапазон — [0, 24].
  • Также есть ограничение: допустимый диапазон для integer_bit_num + fraction_bit_num — [0, 64].
  • col1: Индексный столбец. Поддерживаемые типы: UInt8/UInt16/UInt32/Int8/Int16/Int32.
  • col2: Столбец значений. Поддерживаемые типы: Int8/Int16/Int32/Int64/UInt8/UInt16/UInt32/UInt64/Float32/Float64.
Возвращаемое значение Значение типа Float64, представляющее сумму всех значений. Пример Тестовые данные:
UserID  PlayTime
1       10
2       20
3       30
Запрос & результат:
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
└─────┴──────────────────────────────────────────────────────────────────────────┴───────────────────────────────────────┘
Документация ниже сгенерирована из системной таблицы system.functions.

numericIndexedVectorAllValueSum

Добавленный в: v25.7.0 Возвращает сумму всех значений из numericIndexedVector. Синтаксис
numericIndexedVectorAllValueSum(v)
Аргументы Возвращаемое значение Возвращает сумму. Float64 Примеры Пример использования
Query
SELECT numericIndexedVectorAllValueSum(numericIndexedVectorBuild(mapFromArrays([1, 2, 3], [10, 20, 30]))) AS res;
Response
┌─res─┐
│  60 │
└─────┘

numericIndexedVectorBuild

Добавленный в: v25.7.0 Создаёт NumericIndexedVector из Map. Ключи Map представляют индекс вектора, а значения Map — значения вектора. Синтаксис
numericIndexedVectorBuild(map)
Аргументы
  • map — сопоставление индексов со значениями. Map
Возвращаемое значение Возвращает объект NumericIndexedVector. AggregateFunction Примеры Пример использования
Query
SELECT numericIndexedVectorBuild(mapFromArrays([1, 2, 3], [10, 20, 30])) AS res, toTypeName(res);
Response
┌─res─┬─toTypeName(res)────────────────────────────────────────────┐
│     │ AggregateFunction(groupNumericIndexedVector, UInt8, UInt8) │
└─────┴────────────────────────────────────────────────────────────┘

numericIndexedVectorCardinality

Добавленный в: v25.7.0 Возвращает мощность (количество уникальных индексов) в numericIndexedVector. Синтаксис
numericIndexedVectorCardinality(v)
Аргументы Возвращаемое значение Возвращает количество уникальных индексов. UInt64 Примеры Пример использования
Query
SELECT numericIndexedVectorCardinality(numericIndexedVectorBuild(mapFromArrays([1, 2, 3], [10, 20, 30]))) AS res;
Response
┌─res─┐
│  3  │
└─────┘

numericIndexedVectorGetValue

Добавленный в: v25.7.0 Возвращает значение по указанному индексу из numericIndexedVector. Синтаксис
numericIndexedVectorGetValue(v, i)
Аргументы Возвращаемое значение Числовое значение того же типа, что и тип значения NumericIndexedVector. (U)Int* или Float* Примеры Пример использования
Query
SELECT numericIndexedVectorGetValue(numericIndexedVectorBuild(mapFromArrays([1, 2, 3], [10, 20, 30])), 3) AS res;
Response
┌─res─┐
│  30 │
└─────┘

numericIndexedVectorPointwiseAdd

Добавленный в: v25.7.0 Выполняет покомпонентное сложение numericIndexedVector с другим numericIndexedVector или с числовой константой. Синтаксис
numericIndexedVectorPointwiseAdd(v1, v2)
Аргументы Возвращаемое значение Возвращает новый объект numericIndexedVector. Примеры Пример использования
Query
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;
Response
┌─res1──────────────────┬─res2─────────────┐
│ {1:10,2:30,3:50,4:30} │ {1:12,2:22,3:32} │
└───────────────────────┴──────────────────┘

numericIndexedVectorPointwiseDivide

Добавленный в: v25.7.0 Выполняет покомпонентное деление numericIndexedVector на другой numericIndexedVector или числовую константу. Синтаксис
numericIndexedVectorPointwiseDivide(v1, v2)
Аргументы Возвращаемое значение Новый объект numericIndexedVector Примеры Пример использования
Query
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;
Response
┌─res1────────┬─res2────────────┐
│ {2:2,3:1.5} │ {1:5,2:10,3:15} │
└─────────────┴─────────────────┘

numericIndexedVectorPointwiseEqual

Добавленный в: v25.7.0 Выполняет покомпонентное сравнение numericIndexedVector с другим numericIndexedVector или числовой константой. В результате возвращается numericIndexedVector, содержащий индексы, в которых значения равны, при этом все соответствующие значения устанавливаются в 1. Синтаксис
numericIndexedVectorPointwiseEqual(v1, v2)
Аргументы Возвращаемое значение Возвращает новый объект numericIndexedVector Примеры
Query
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;
Response
┌─res1──┬─res2──┐
│ {2:1} │ {2:1} │
└───────┴───────┘

numericIndexedVectorPointwiseGreater

Добавленный в: v25.7.0 Выполняет покомпонентное сравнение между numericIndexedVector и другим numericIndexedVector либо числовой константой. В результате возвращается numericIndexedVector, содержащий индексы, в которых значение первого вектора больше значения второго, при этом все соответствующие значения устанавливаются равными 1. Синтаксис
numericIndexedVectorPointwiseGreater(v1, v2)
Аргументы Возвращаемое значение Возвращает новый объект numericIndexedVector. Примеры Пример использования
Query
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;
Response
┌─res1──────┬─res2──┐
│ {1:1,3:1} │ {3:1} │
└───────────┴───────┘

numericIndexedVectorPointwiseGreaterEqual

Добавленный в: v25.7.0 Выполняет покомпонентное сравнение между numericIndexedVector и либо другим numericIndexedVector, либо числовой константой. В результате возвращается numericIndexedVector, содержащий индексы, в которых значение первого вектора больше или равно значению второго вектора, при этом все соответствующие значения устанавливаются в 1. Синтаксис
numericIndexedVectorPointwiseGreaterEqual(v1, v2)
Аргументы Возвращаемое значение Возвращает новый объект numericIndexedVector. Примеры Пример использования
Query
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;
Response
┌─res1──────────┬─res2──────┐
│ {1:1,2:1,3:1} │ {2:1,3:1} │
└───────────────┴───────────┘

numericIndexedVectorPointwiseLess

Добавленный в: v25.7.0 Выполняет покомпонентное сравнение между numericIndexedVector и другим numericIndexedVector либо числовой константой. В результате получается numericIndexedVector, содержащий индексы, в которых значение первого вектора меньше значения второго, при этом все соответствующие значения устанавливаются в 1. Синтаксис
numericIndexedVectorPointwiseLess(v1, v2)
Аргументы Возвращаемое значение Возвращает новый объект numericIndexedVector. Примеры Пример использования
Query
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;
Response
┌─res1──────┬─res2──┐
│ {3:1,4:1} │ {1:1} │
└───────────┴───────┘

numericIndexedVectorPointwiseLessEqual

Добавленный в: v25.7.0 Выполняет покомпонентное сравнение между numericIndexedVector и другим numericIndexedVector либо числовой константой. Результатом является numericIndexedVector, содержащий индексы, в которых значение первого вектора меньше или равно значению второго вектора; все соответствующие значения при этом устанавливаются в 1. Синтаксис
numericIndexedVectorPointwiseLessEqual(v1, v2)
Аргументы Возвращаемое значение Новый объект numericIndexedVector Примеры Пример использования
Query
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;
Response
┌─res1──────────┬─res2──────┐
│ {2:1,3:1,4:1} │ {1:1,2:1} │
└───────────────┴───────────┘

numericIndexedVectorPointwiseMultiply

Добавленный в: v25.7.0 Выполняет покомпонентное умножение numericIndexedVector либо на другой numericIndexedVector, либо на числовую константу. Синтаксис
numericIndexedVectorPointwiseMultiply(v1, v2)
Аргументы Возвращаемое значение Возвращает новый объект numericIndexedVector. numericIndexedVector Примеры
Query
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;
Response
┌─res1──────────┬─res2─────────────┐
│ {2:200,3:600} │ {1:20,2:40,3:60} │
└───────────────┴──────────────────┘

numericIndexedVectorPointwiseNotEqual

Добавленный в: v25.7.0 Выполняет покомпонентное сравнение между numericIndexedVector и либо другим numericIndexedVector, либо числовой константой. В результате возвращается numericIndexedVector, содержащий индексы, в которых значения не равны, при этом все соответствующие значения устанавливаются равными 1. Синтаксис
numericIndexedVectorPointwiseNotEqual(v1, v2)
Аргументы Возвращаемое значение Возвращает новый объект numericIndexedVector. numericIndexedVector Примеры Пример использования
Query
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;
Response
┌─res1──────────┬─res2──────┐
│ {1:1,3:1,4:1} │ {1:1,3:1} │
└───────────────┴───────────┘

numericIndexedVectorPointwiseSubtract

Добавленный в: v25.7.0 Выполняет покомпонентное вычитание между numericIndexedVector и другим numericIndexedVector либо числовой константой. Синтаксис
numericIndexedVectorPointwiseSubtract(v1, v2)
Аргументы Возвращаемое значение Возвращает новый объект numericIndexedVector. Примеры Пример использования
Query
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;
Response
┌─res1───────────────────┬─res2────────────┐
│ {1:10,2:10,3:10,4:-30} │ {1:8,2:18,3:28} │
└────────────────────────┴─────────────────┘

numericIndexedVectorShortDebugString

Добавленный в: v25.7.0 Возвращает внутреннюю информацию о numericIndexedVector в формате JSON. Эта функция в основном используется для отладки. Синтаксис
numericIndexedVectorShortDebugString(v)
Аргументы Возвращаемое значение Возвращает JSON-строку с отладочной информацией. String Примеры Пример использования
Query
SELECT numericIndexedVectorShortDebugString(numericIndexedVectorBuild(mapFromArrays([1, 2, 3], [10, 20, 30]))) AS res\G;
Response
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

Добавленный в: v25.7.0 Преобразует numericIndexedVector в Map. Синтаксис
numericIndexedVectorToMap(v)
Аргументы Возвращаемое значение Возвращает карту с парами «индекс — значение». Map Примеры Пример использования
Query
SELECT numericIndexedVectorToMap(numericIndexedVectorBuild(mapFromArrays([1, 2, 3], [10, 20, 30]))) AS res;
Response
┌─res──────────────┐
│ {1:10,2:20,3:30} │
└──────────────────┘
Последнее изменение 10 июня 2026 г.