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.
Синтаксис
Параметры
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, представляющее сумму всех значений.
Пример
Тестовые данные:
Запрос и результат:
Приведённая ниже документация сгенерирована из системной таблицы system.functions.