Перейти к основному содержимому
Перейти к основному содержимому

NumericIndexedVector

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, при этом bitmap хранит индексы. Roaring Bitmap используется как конкретная реализация bitmap. Рекомендуемой практикой является по возможности концентрировать индексы в небольшом числе контейнеров Roaring Bitmap для максимизации степени сжатия и производительности запросов.
  • Механизм Bit-Sliced Index преобразует значение в двоичное представление. Для типов с плавающей запятой используется фиксированное-точечное представление (fixed-point), что может приводить к потере точности. Точность можно регулировать, настраивая количество бит, отводимых под дробную часть; по умолчанию используется 24 бита, чего достаточно для большинства сценариев. Вы можете настроить количество бит для целой и дробной части при конструировании NumericIndexedVector с помощью агрегатной функции groupNumericIndexedVector с суффиксом -State.
  • Для индексов возможны три состояния: ненулевое значение, нулевое значение и отсутствие. В NumericIndexedVector хранятся только ненулевые и нулевые значения. Кроме того, в поэлементных операциях между двумя NumericIndexedVector значение отсутствующего индекса трактуется как 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.

Примеры

Пример использования

SELECT numericIndexedVectorAllValueSum(numericIndexedVectorBuild(mapFromArrays([1, 2, 3], [10, 20, 30]))) AS res;
┌─res─┐
│  60 │
└─────┘

numericIndexedVectorBuild

Введена в версии: v25.7.0

Создаёт NumericIndexedVector из map. Ключи map соответствуют индексам вектора, а значения map — значениям вектора.

Синтаксис

numericIndexedVectorBuild(map)

Аргументы

  • map — отображение индекса в значение. Map

Возвращаемое значение

Возвращает объект NumericIndexedVector. AggregateFunction

Примеры

Пример использования

SELECT numericIndexedVectorBuild(mapFromArrays([1, 2, 3], [10, 20, 30])) AS res, toTypeName(res);
┌─res─┬─toTypeName(res)────────────────────────────────────────────┐
│     │ AggregateFunction(groupNumericIndexedVector, UInt8, UInt8) │
└─────┴────────────────────────────────────────────────────────────┘

numericIndexedVectorCardinality

Впервые появилась в: v25.7.0

Возвращает кардинальность (количество уникальных индексов) numericIndexedVector.

Синтаксис

numericIndexedVectorCardinality(v)

Аргументы

Возвращаемое значение

Возвращает количество уникальных индексов. UInt64

Примеры

Пример использования

SELECT numericIndexedVectorCardinality(numericIndexedVectorBuild(mapFromArrays([1, 2, 3], [10, 20, 30]))) AS res;
┌─res─┐
│  3  │
└─────┘

numericIndexedVectorGetValue

Добавлен в версии: v25.7.0

Извлекает значение, соответствующее указанному индексу, из numericIndexedVector.

Синтаксис

numericIndexedVectorGetValue(v, i)

Аргументы

Возвращаемое значение

Числовое значение того же типа, что и тип значения NumericIndexedVector: (U)Int* или Float*

Примеры

Пример использования

SELECT numericIndexedVectorGetValue(numericIndexedVectorBuild(mapFromArrays([1, 2, 3], [10, 20, 30])), 3) AS res;
┌─res─┐
│  30 │
└─────┘

numericIndexedVectorPointwiseAdd

Добавлена в: v25.7.0

Выполняет покомпонентное сложение между numericIndexedVector и другим numericIndexedVector или числовой константой.

Синтаксис

numericIndexedVectorPointwiseAdd(v1, v2)

Аргументы

Возвращаемое значение

Возвращает новый объект типа numericIndexedVector. numericIndexedVector

Примеры

Пример использования

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

Введена в версии: v25.7.0

Выполняет покомпонентное деление между numericIndexedVector и другим numericIndexedVector или числовой константой.

Синтаксис

numericIndexedVectorPointwiseDivide(v1, v2)

Аргументы

Возвращаемое значение

Возвращает новый объект numericIndexedVector. numericIndexedVector

Примеры

Пример использования

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

Введена в версии: v25.7.0

Выполняет поэлементное сравнение между numericIndexedVector и другим numericIndexedVector или числовой константой. Результатом является numericIndexedVector, содержащий индексы элементов с равными значениями; всем соответствующим значениям присваивается 1.

Синтаксис

numericIndexedVectorPointwiseEqual(v1, v2)

Аргументы

Возвращаемое значение

Возвращает новый объект numericIndexedVector. numericIndexedVector

Примеры


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

Впервые представлено в: v25.7.0

Выполняет поэлементное сравнение между numericIndexedVector и другим numericIndexedVector или числовой константой. Результатом является numericIndexedVector, содержащий индексы, для которых значение первого вектора больше значения второго, при этом все соответствующие значения равны 1.

Синтаксис

numericIndexedVectorPointwiseGreater(v1, v2)

Аргументы

Возвращаемое значение

Возвращает новый объект типа numericIndexedVector.

Примеры

Пример использования

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

Добавлено в: v25.7.0

Выполняет покомпонентное сравнение между numericIndexedVector и другим numericIndexedVector или числовой константой. Результатом является numericIndexedVector, содержащий индексы позиций, где значение первого вектора больше либо равно значению второго вектора, при этом все соответствующие значения устанавливаются в 1.

Синтаксис

numericIndexedVectorPointwiseGreaterEqual(v1, v2)

Аргументы

Возвращаемое значение

Возвращает новый объект типа numericIndexedVector. numericIndexedVector

Примеры

Пример использования

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

Введено в версии: v25.7.0

Выполняет поэлементное сравнение между numericIndexedVector и либо другим numericIndexedVector, либо числовой константой. Результатом является numericIndexedVector, содержащий индексы тех элементов, для которых значение первого вектора меньше значения второго, при этом все соответствующие значения равны 1.

Синтаксис

numericIndexedVectorPointwiseLess(v1, v2)

Аргументы

Возвращаемое значение

Возвращает новый объект numericIndexedVector. numericIndexedVector

Примеры

Пример использования

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

Добавлена в версии: v25.7.0

Выполняет поэлементное сравнение между numericIndexedVector и другим numericIndexedVector или числовой константой. Результатом является numericIndexedVector, содержащий индексы, где значение первого вектора меньше либо равно значению второго вектора, при этом все соответствующие значения равны 1.

Синтаксис

numericIndexedVectorPointwiseLessEqual(v1, v2)

Аргументы

Возвращаемое значение

Возвращает новый объект numericIndexedVector. numericIndexedVector

Примеры

Пример использования

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

Введена в версии v25.7.0

Выполняет покомпонентное умножение numericIndexedVector на другой numericIndexedVector или числовую константу.

Синтаксис

numericIndexedVectorPointwiseMultiply(v1, v2)

Аргументы

Возвращаемое значение

Возвращает новый объект numericIndexedVector. numericIndexedVector

Примеры


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

Введено в: v25.7.0

Выполняет поэлементное сравнение между numericIndexedVector и либо другим numericIndexedVector, либо числовой константой. Результатом является numericIndexedVector, содержащий индексы, в которых значения не равны, при этом все соответствующие значения равны 1.

Синтаксис

numericIndexedVectorPointwiseNotEqual(v1, v2)

Аргументы

Возвращаемое значение

Возвращает новый объект numericIndexedVector. numericIndexedVector

Примеры

Пример использования

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

Введена в версии: v25.7.0

Выполняет покомпонентное вычитание между numericIndexedVector и другим numericIndexedVector или числовой константой.

Синтаксис

numericIndexedVectorPointwiseSubtract(v1, v2)

Аргументы

Возвращаемое значение

Возвращает новый объект numericIndexedVector. numericIndexedVector

Примеры

Пример использования

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

Появилась в версии: v25.7.0

Возвращает внутреннюю информацию о numericIndexedVector в формате JSON. Эта функция в первую очередь используется для отладки.

Синтаксис

numericIndexedVectorShortDebugString(v)

Аргументы

Возвращаемое значение

Возвращает JSON-строку с отладочной информацией. String

Примеры

Пример использования

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

Добавлено в: v25.7.0

Преобразует numericIndexedVector в map.

Синтаксис

numericIndexedVectorToMap(v)

Аргументы

Возвращаемое значение

Возвращает значение типа Map с парами индекс–значение.

Примеры

Пример использования

SELECT numericIndexedVectorToMap(numericIndexedVectorBuild(mapFromArrays([1, 2, 3], [10, 20, 30]))) AS res;
┌─res──────────────┐
│ {1:10,2:20,3:30} │
└──────────────────┘