ClickHouse/docs/ru/agg_functions/reference.md
Alex Bocharov 9963e2f160 Fix uniqHLL12 and uniqCombined for cardinalities 100M+.
* Changing size() return type from UInt32 to UInt64 to prevent overflow (this shouldn't break back compatibility).
 * Removing "big cardinalities fix" for cardinalities >2^32/30 as it was very inaccurate and for estimates >2^32 it was trying to do 'log' of negative number which is NaN and it was casted to 0.
 * Adding python script to show that intHash32 is not a good choice for HyperLogLog algorithm when it's used for linear counting branch of it.
 * Adding bash script to test uniq, uniqHLL12, uniqCombined on different set cardinalities.
 * Altering documentation of uniq* aggregate functions with recommendations to use uniq instead of uniqHLL12 or uniqCombined.
2018-01-31 11:36:01 +00:00

26 KiB
Raw Blame History

Справочник функций

count()

Считает количество строк. Принимает ноль аргументов, возвращает UInt64. Не поддерживается синтаксис COUNT(DISTINCT x) - для этого есть отдельная агрегатная функция uniq.

Запрос вида SELECT count() FROM table не оптимизируется, так как количество записей в таблице нигде не хранится отдельно - из таблицы будет выбран какой-нибудь достаточно маленький столбец, и будет посчитано количество значений в нём.

any(x)

Выбирает первое попавшееся значение. Порядок выполнения запроса может быть произвольным и даже каждый раз разным, поэтому результат данной функции недетерминирован. Для получения детерминированного результата, можно использовать функции min или max вместо any.

В некоторых случаях, вы всё-таки можете рассчитывать на порядок выполнения запроса. Это - случаи, когда SELECT идёт из подзапроса, в котором используется ORDER BY.

При наличии в запросе SELECT секции GROUP BY или хотя бы одной агрегатной функции, ClickHouse (в отличие от, например, MySQL) требует, чтобы все выражения в секциях SELECT, HAVING, ORDER BY вычислялись из ключей или из агрегатных функций. То есть, каждый выбираемый из таблицы столбец, должен использоваться либо в ключах, либо внутри агрегатных функций. Чтобы получить поведение, как в MySQL, вы можете поместить остальные столбцы в агрегатную функцию any.

anyHeavy

Выбирает часто встречающееся значение с помощью алгоритма "heavy hitters". Если существует значение, которое встречается чаще, чем в половине случаев, в каждом потоке выполнения запроса, то возвращается данное значение. В общем случае, результат недетерминирован.

anyHeavy(column)

Аргументы

  • column - Имя столбца.

Пример

Возьмем набор данных OnTime и выберем произвольное часто встречающееся значение в столбце AirlineID.

SELECT anyHeavy(AirlineID) AS res
FROM ontime
┌───res─┐
│ 19690 │
└───────┘

anyLast(x)

Выбирает последнее попавшееся значение. Результат так же недетерминирован, как и для функции any.

min(x)

Вычисляет минимум.

max(x)

Вычисляет максимум.

argMin(arg, val)

Вычисляет значение arg при минимальном значении val. Если есть несколько разных значений arg для минимальных значений val, то выдаётся первое попавшееся из таких значений.

argMax(arg, val)

Вычисляет значение arg при максимальном значении val. Если есть несколько разных значений arg для максимальных значений val, то выдаётся первое попавшееся из таких значений.

sum(x)

Вычисляет сумму. Работает только для чисел.

sumWithOverflow(x)

Вычисляет сумму чисел, используя для результата тот же тип данных, что и для входных параметров. Если сумма выйдет за максимальное значение для заданного типа данных, то функция вернёт ошибку.

Работает только для чисел.

sumMap(key, value)

Производит суммирование массива 'value' по соотвествующим ключам заданным в массиве 'key'. Количество элементов в 'key' и 'value' должно быть одинаковым для каждой строки, для которой происходит суммирование. Возвращает кортеж из двух массивов - ключи в отсортированном порядке и значения, просуммированные по соотвествующим ключам.

Пример:

CREATE TABLE sum_map(
    date Date,
    timeslot DateTime,
    statusMap Nested(
        status UInt16,
        requests UInt64
    )
) ENGINE = Log;
INSERT INTO sum_map VALUES
    ('2000-01-01', '2000-01-01 00:00:00', [1, 2, 3], [10, 10, 10]),
    ('2000-01-01', '2000-01-01 00:00:00', [3, 4, 5], [10, 10, 10]),
    ('2000-01-01', '2000-01-01 00:01:00', [4, 5, 6], [10, 10, 10]),
    ('2000-01-01', '2000-01-01 00:01:00', [6, 7, 8], [10, 10, 10]);
SELECT
    timeslot,
    sumMap(statusMap.status, statusMap.requests)
FROM sum_map
GROUP BY timeslot
┌────────────timeslot─┬─sumMap(statusMap.status, statusMap.requests)─┐
│ 2000-01-01 00:00:00 │ ([1,2,3,4,5],[10,10,20,10,10])               │
│ 2000-01-01 00:01:00 │ ([4,5,6,7,8],[10,10,20,10,10])               │
└─────────────────────┴──────────────────────────────────────────────┘

avg(x)

Вычисляет среднее. Работает только для чисел. Результат всегда - Float64.

uniq(x)

Приближённо вычисляет количество различных значений аргумента. Работает для чисел, строк, дат, дат-с-временем, для нескольких аргументов и аргументов-кортежей.

Используется алгоритм типа adaptive sampling: в качестве состояния вычислений используется выборка значений хэшей элементов, размером до 65536. Алгоритм является очень точным для множеств небольшой кардинальности (до 65536) и очень эффективным по CPU (при расчёте не слишком большого количества таких функций, использование uniq почти так же быстро, как использование других агрегатных функций).

Результат детерминирован (не зависит от порядка выполнения запроса).

Данная функция обеспечивает отличную точность даже для множеств огромной кардинальности (10B+ элементов) и рекомендуется к использованию по умолчанию.

uniqCombined(x)

Приближённо вычисляет количество различных значений аргумента. Работает для чисел, строк, дат, дат-с-временем, для нескольких аргументов и аргументов-кортежей.

Используется комбинация трёх алгоритмов: массив, хэш-таблица и HyperLogLog с таблицей коррекции погрешности. Расход памяти в несколько раз меньше, чем у функции uniq, а точность в несколько раз выше. Скорость работы чуть ниже, чем у функции uniq, но иногда может быть даже выше - в случае распределённых запросов, в которых по сети передаётся большое количество состояний агрегации. Максимальный размер состояния составляет 96 KiB (HyperLogLog из 217 6-битовых ячеек).

Результат детерминирован (не зависит от порядка выполнения запроса).

Функция uniqCombined является хорошим выбором по умолчанию для подсчёта количества различных значений, но стоит иметь ввиду что для множеств большой кардинальности (200M+) ошибка оценки будет только расти и для множеств огромной кардинальности (1B+ элементов) функция возвращает результат с очень большой неточностью.

uniqHLL12(x)

Приближённо вычисляет количество различных значений аргумента, используя алгоритм HyperLogLog. Используется 212 5-битовых ячеек. Размер состояния чуть больше 2.5 КБ. Результат является не точным(ошибка до ~10%) для небольших множеств (<10K элементов), но для множеств большой кардинальности (10K - 100M) результат довольно точен (ошибка до ~1.6%) и начиная с 100M ошибка оценки будет только расти и для множеств огромной кардинальности (1B+ элементов) функция возвращает результат с очень большой неточностью.

Результат детерминирован (не зависит от порядка выполнения запроса).

Данная функция не рекомендуется к использованию, и в большинстве случаев, используйте функцию uniq или uniqCombined.

uniqExact(x)

Вычисляет количество различных значений аргумента, точно. Не стоит бояться приближённых расчётов. Поэтому, используйте лучше функцию uniq. Функцию uniqExact следует использовать, если вам точно нужен точный результат.

Функция uniqExact расходует больше оперативки, чем функция uniq, так как размер состояния неограниченно растёт по мере роста количества различных значений.

groupArray(x), groupArray(max_size)(x)

Составляет массив из значений аргумента. Значения в массив могут быть добавлены в любом (недетерминированном) порядке.

Вторая версия (с параметром max_size) ограничивает размер результирующего массива max_size элементами. Например, groupArray(1)(x) эквивалентно [any(x)].

В некоторых случаях, вы всё же можете рассчитывать на порядок выполнения запроса. Это — случаи, когда SELECT идёт из подзапроса, в котором используется ORDER BY.

groupArrayInsertAt

Вставляет в массив значение в заданную позицию.

Принимает на вход значение и позицию. Если на одну и ту же позицию вставляется несколько значений, в результирующем массиве может оказаться любое (первое в случае однопоточного выполнения). Если в позицию не вставляется ни одного значения, то позиции присваивается значение по умолчанию.

Опциональные параметры:

  • Значение по умолчанию для подстановки на пустые позиции.
  • Длина результирующего массива. Например, если вы хотите получать массисы одинакового размера для всех агрегатных ключей. При использовании этого параметра значение по умолчанию задавать обязательно.

groupUniqArray(x)

Составляет массив из различных значений аргумента. Расход оперативки такой же, как у функции uniqExact.

quantile(level)(x)

Приближённо вычисляет квантиль уровня level. level - константа, число с плавающей запятой от 0 до 1. Рекомендуется использовать значения level в диапазоне 0.01..0.99. Не используйте значения level, равные 0 или 1 - для таких случаев есть функции min и max.

В этой функции, равно как и во всех функциях для расчёта квантилей, параметр level может быть не указан. В таком случае, он принимается равным 0.5 - то есть, функция будет вычислять медиану.

Работает для чисел, дат, дат-с-временем. Для чисел возвращает Float64, для дат - дату, для дат-с-временем - дату-с-временем.

Используется reservoir sampling с размером резервуара до 8192. При необходимости, результат выдаётся с линейной аппроксимацией из двух соседних значений. Этот алгоритм обеспечивает весьма низкую точность расчёта. Смотрите также функции quantileTiming, quantileTDigest, quantileExact.

Результат зависит от порядка выполнения запроса, и является недетерминированным.

При использовании нескольких функций quantile (и аналогичных) с разными уровнями в запросе, внутренние состояния не объединяются (то есть, запрос работает менее эффективно, чем мог бы). В этом случае, используйте функцию quantiles (и аналогичные).

quantileDeterministic(level)(x, determinator)

Работает аналогично функции quantile, но, в отличие от неё, результат является детерминированным и не зависит от порядка выполнения запроса.

Для этого, функция принимает второй аргумент - «детерминатор». Это некоторое число, хэш от которого используется вместо генератора случайных чисел в алгоритме reservoir sampling. Для правильной работы функции, одно и то же значение детерминатора не должно встречаться слишком часто. В качестве детерминатора вы можете использовать идентификатор события, идентификатор посетителя и т. п.

Не используйте эту функцию для рассчёта таймингов. Для этого есть более подходящая функции - quantileTiming.

quantileTiming(level)(x)

Вычисляет квантиль уровня level с фиксированной точностью. Работает для чисел. Предназначена для расчёта квантилей от времени загрузки страницы в миллисекундах.

Если значение больше 30000 (соответствует времени загрузки страницы большем 30 секундам) - результат приравнивается к 30000.

Если всего значений не больше примерно 5670, то вычисление точное.

Иначе:

  • если время меньше 1024 мс., то вычисление точное.
  • иначе вычисление идёт с округлением до числа, кратного 16 мс.

При передаче в функцию отрицательных значений, поведение не определено.

Возвращаемое значение имеет тип Float32. Когда в функцию не было передано ни одного значения (при использовании quantileTimingIf), возвращается nan. Это сделано, чтобы отличать такие случаи от нулей. Смотрите замечание о сортировке NaN-ов в разделе «Секция ORDER BY».

Результат детерминирован (не зависит от порядка выполнения запроса).

Для своей задачи (расчёт квантилей времени загрузки страниц), использование этой функции эффективнее и результат точнее, чем для функции quantile.

quantileTimingWeighted(level)(x, weight)

Отличается от функции medianTiming наличием второго аргумента - «веса». Вес - неотрицательное целое число. Результат считается так же, как если бы в функцию medianTiming` значение x было передано weight количество раз.

quantileExact(level)(x)

Вычисляет квантиль уровня level точно. Для этого, все переданные значения складываются в массив, который затем частично сортируется. Поэтому, функция потребляет O(n) памяти, где n - количество переданных значений. Впрочем, для случая маленького количества значений, функция весьма эффективна.

quantileExactWeighted(level)(x, weight)

Вычисляет квантиль уровня level точно. При этом, каждое значение учитывается с весом weight - как будто оно присутствует weight раз. Аргументы функции можно рассматривать как гистограммы, где значению x соответствует «столбик» гистограммы высоты weight, а саму функцию можно рассматривать как суммирование гистограмм.

В качестве алгоритма используется хэш-таблица. Из-за этого, в случае, если передаваемые значения часто повторяются, функция потребляет меньше оперативки, чем quantileExact. Вы можете использовать эту функцию вместо quantileExact, указав в качестве веса число 1.

quantileTDigest(level)(x)

Вычисляет квантиль уровня level приближённо, с использованием алгоритма t-digest. Максимальная погрешность составляет 1%. Расход памяти на состояние пропорционален логарифму от количества переданных значений.

Производительность функции ниже quantile, quantileTiming. По соотношению размера состояния и точности, функция существенно лучше, чем quantile.

Результат зависит от порядка выполнения запроса, и является недетерминированным.

median

Для всех quantile-функций, также присутствуют соответствующие median-функции: median, medianDeterministic, medianTiming, medianTimingWeighted, medianExact, medianExactWeighted, medianTDigest. Они являются синонимами и их поведение ничем не отличается.

quantiles(level1, level2, ...)(x)

Для всех quantile-функций, также присутствуют соответствующие quantiles-функции: quantiles, quantilesDeterministic, quantilesTiming, quantilesTimingWeighted, quantilesExact, quantilesExactWeighted, quantilesTDigest. Эти функции за один проход вычисляют все квантили перечисленных уровней и возвращают массив вычисленных значений.

varSamp(x)

Вычисляет величину Σ((x - x̅)^2) / (n - 1), где n - размер выборки, - среднее значение x.

Она представляет собой несмещённую оценку дисперсии случайной величины, если переданные в функцию значения являются выборкой этой случайной величины.

Возвращает Float64. В случае, когда n <= 1, возвращается +∞.

varPop(x)

Вычисляет величину Σ((x - x̅)^2) / n, где n - размер выборки, - среднее значение x.

То есть, дисперсию для множества значений. Возвращает Float64.

stddevSamp(x)

Результат равен квадратному корню от varSamp(x).

stddevPop(x)

Результат равен квадратному корню от varPop(x).

topK

Возвращает массив наиболее часто встречающихся значений в указанном столбце. Результирующий массив упорядочен по убыванию частоты значения (не по самим значениям).

Реализует Filtered Space-Saving алгоритм для анализа TopK, на основе reduce-and-combine алгоритма из методики Parallel Space Saving.

topK(N)(column)

Функция не дает гарантированного результата, при определенных условиях возможны ошибки и вернутся частые, но не наиболее частые значения.

Рекомендуем использовать значения N < 10, при больших N снижается производительность. Максимально возможное значение N = 65536.

Аргументы

  • 'N' - Количество значений.
  • 'x' - Столбец.

Пример

Возьмем набор данных OnTime и выберем 3 наиболее часто встречающихся значения в столбце AirlineID.

SELECT topK(3)(AirlineID) AS res
FROM ontime
┌─res─────────────────┐
│ [19393,19790,19805] │
└─────────────────────┘

covarSamp(x, y)

Вычисляет величину Σ((x - x̅)(y - y̅)) / (n - 1).

Возвращает Float64. В случае, когда n <= 1, возвращается +∞.

covarPop(x, y)

Вычисляет величину Σ((x - x̅)(y - y̅)) / n.

corr(x, y)

Вычисляет коэффициент корреляции Пирсона: Σ((x - x̅)(y - y̅)) / sqrt(Σ((x - x̅)^2) * Σ((y - y̅)^2)).