diff --git a/dbms/include/DB/AggregateFunctions/AggregateFunctionUniq.h b/dbms/include/DB/AggregateFunctions/AggregateFunctionUniq.h index 95a37166c34..e8fbfe59e4b 100644 --- a/dbms/include/DB/AggregateFunctions/AggregateFunctionUniq.h +++ b/dbms/include/DB/AggregateFunctions/AggregateFunctionUniq.h @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -46,20 +47,35 @@ template <> struct AggregateFunctionUniqTraits }; -struct AggregateFunctionUniqData +struct AggregateFunctionUniqUniquesHashSetData { - UniquesHashSet set; + typedef UniquesHashSet Set; + Set set; + + static String getName() { return "uniq"; } }; +struct AggregateFunctionUniqHLL12Data +{ + typedef HyperLogLogCounter<12> Set; + Set set; + + static String getName() { return "uniqHLL12"; } +}; + +/// Структура для делегации работы по добавлению одного элемента +/// в аггрегатную функцию uniq. Используется для частичной специализации +/// для добавления строк. +template struct OneAdder; /// Приближённо вычисляет количество различных значений. -template -class AggregateFunctionUniq : public IUnaryAggregateFunction +template +class AggregateFunctionUniq : public IUnaryAggregateFunction { public: AggregateFunctionUniq() {} - String getName() const { return "uniq"; } + String getName() const { return Data::getName(); } DataTypePtr getReturnType() const { @@ -72,50 +88,66 @@ public: void addOne(AggregateDataPtr place, const IColumn & column, size_t row_num) const { - data(place).set.insert(AggregateFunctionUniqTraits::hash(static_cast &>(column).getData()[row_num])); + OneAdder::addOne(*this, place, column, row_num); } void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs) const { - data(place).set.merge(data(rhs).set); + this->data(place).set.merge(this->data(rhs).set); } void serialize(ConstAggregateDataPtr place, WriteBuffer & buf) const { - data(place).set.write(buf); + this->data(place).set.write(buf); } void deserializeMerge(AggregateDataPtr place, ReadBuffer & buf) const { - UniquesHashSet tmp_set; + typename Data::Set tmp_set; tmp_set.read(buf); - data(place).set.merge(tmp_set); + this->data(place).set.merge(tmp_set); } void insertResultInto(ConstAggregateDataPtr place, IColumn & to) const { - static_cast(to).getData().push_back(data(place).set.size()); + static_cast(to).getData().push_back(this->data(place).set.size()); + } + +private: + template friend struct OneAdder; +}; + +template +struct OneAdder +{ + static void addOne(const AggregateFunctionUniq & aggregate_function, AggregateDataPtr place, const IColumn & column, size_t row_num) + { + aggregate_function.data(place).set.insert( + AggregateFunctionUniqTraits::hash(static_cast &>(column).getData()[row_num])); } }; -template <> -inline void AggregateFunctionUniq::addOne(AggregateDataPtr place, const IColumn & column, size_t row_num) const +template +struct OneAdder { - /// Имейте ввиду, что вычисление приближённое. - StringRef value = column.getDataAt(row_num); - data(place).set.insert(CityHash64(value.data, value.size)); -} + static void addOne(const AggregateFunctionUniq & aggregate_function, AggregateDataPtr place, const IColumn & column, size_t row_num) + { + /// Имейте ввиду, что вычисление приближённое. + StringRef value = column.getDataAt(row_num); + aggregate_function.data(place).set.insert(CityHash64(value.data, value.size)); + } +}; /** То же самое, но выводит состояние вычислений в строке в текстовом виде. * Используется, если какой-то внешней программе (сейчас это ███████████) * надо получить это состояние и потом использовать по-своему. */ -template -class AggregateFunctionUniqState : public AggregateFunctionUniq +template +class AggregateFunctionUniqState : public AggregateFunctionUniq { public: - String getName() const { return "uniqState"; } + String getName() const { return Data::getName() + "State"; } DataTypePtr getReturnType() const { @@ -139,7 +171,7 @@ public: * Приближённо считает количество различных значений, когда выполнено это условие. */ template -class AggregateFunctionUniqIf : public IAggregateFunctionHelper +class AggregateFunctionUniqIf : public IAggregateFunctionHelper { public: AggregateFunctionUniqIf() {} diff --git a/dbms/src/AggregateFunctions/AggregateFunctionFactory.cpp b/dbms/src/AggregateFunctions/AggregateFunctionFactory.cpp index 8cb8c6e1dc7..7321a4a0743 100644 --- a/dbms/src/AggregateFunctions/AggregateFunctionFactory.cpp +++ b/dbms/src/AggregateFunctions/AggregateFunctionFactory.cpp @@ -46,6 +46,23 @@ static IAggregateFunction * createWithNumericType(const IDataType & argument_typ return NULL; } +template