better implementation

This commit is contained in:
Duc Canh Le 2022-08-10 18:56:18 +08:00
parent 9e865d48ce
commit 17fa8076e3

View File

@ -7,6 +7,7 @@
#include <Common/LRUCache.h> #include <Common/LRUCache.h>
#include <Common/assert_cast.h> #include <Common/assert_cast.h>
#include "Columns/IColumn.h" #include "Columns/IColumn.h"
#include "Core/Field.h"
#include <base/unaligned.h> #include <base/unaligned.h>
#include <Columns/ColumnString.h> #include <Columns/ColumnString.h>
@ -15,8 +16,10 @@
#include <Columns/ColumnLowCardinality.h> #include <Columns/ColumnLowCardinality.h>
#include <Core/Defines.h> #include <Core/Defines.h>
#include <functional>
#include <memory> #include <memory>
#include <cassert> #include <cassert>
#include <stddef.h>
namespace DB namespace DB
@ -39,19 +42,27 @@ struct HashMethodOneNumber
using Base = columns_hashing_impl::HashMethodBase<Self, Value, Mapped, use_cache, need_offset>; using Base = columns_hashing_impl::HashMethodBase<Self, Value, Mapped, use_cache, need_offset>;
const char * vec; const char * vec;
bool column_is_const = false; FieldType const_value;
std::function<FieldType(size_t row)> get_key_holder_impl;
/// If the keys of a fixed length then key_sizes contains their lengths, empty otherwise. /// If the keys of a fixed length then key_sizes contains their lengths, empty otherwise.
HashMethodOneNumber(const ColumnRawPtrs & key_columns, const Sizes & /*key_sizes*/, const HashMethodContextPtr &) HashMethodOneNumber(const ColumnRawPtrs & key_columns, const Sizes & /*key_sizes*/, const HashMethodContextPtr &)
{ {
vec = key_columns[0]->getRawData().data; vec = key_columns[0]->getRawData().data;
column_is_const = isColumnConst(*key_columns[0]); if (isColumnConst(*key_columns[0]))
{
const_value = unalignedLoad<FieldType>(vec);
get_key_holder_impl = [this](size_t /*row*/) { return const_value; };
}
else
{
get_key_holder_impl = [this](size_t row) { return unalignedLoad<FieldType>(vec + row * sizeof(FieldType)); };
}
} }
explicit HashMethodOneNumber(const IColumn * column) explicit HashMethodOneNumber(const IColumn * column)
{ {
vec = column->getRawData().data; vec = column->getRawData().data;
column_is_const = isColumnConst(*column);
} }
/// Creates context. Method is called once and result context is used in all threads. /// Creates context. Method is called once and result context is used in all threads.
@ -69,11 +80,7 @@ struct HashMethodOneNumber
using Base::getHash; /// (const Data & data, size_t row, Arena & pool) -> size_t using Base::getHash; /// (const Data & data, size_t row, Arena & pool) -> size_t
/// Is used for default implementation in HashMethodBase. /// Is used for default implementation in HashMethodBase.
FieldType getKeyHolder(size_t row, Arena &) const FieldType getKeyHolder(size_t row, Arena &) const { return get_key_holder_impl(row); }
{
size_t pos = column_is_const ? 0 : row;
return unalignedLoad<FieldType>(vec + pos * sizeof(FieldType));
}
const FieldType * getKeyData() const { return reinterpret_cast<const FieldType *>(vec); } const FieldType * getKeyData() const { return reinterpret_cast<const FieldType *>(vec); }
}; };
@ -89,27 +96,28 @@ struct HashMethodString
const IColumn::Offset * offsets; const IColumn::Offset * offsets;
const UInt8 * chars; const UInt8 * chars;
bool column_is_const = false; std::function<StringRef(size_t row)> get_key_holder_impl;
HashMethodString(const ColumnRawPtrs & key_columns, const Sizes & /*key_sizes*/, const HashMethodContextPtr &) HashMethodString(const ColumnRawPtrs & key_columns, const Sizes & /*key_sizes*/, const HashMethodContextPtr &)
{ {
const IColumn * column = key_columns[0]; const IColumn * column = key_columns[0];
if (isColumnConst(*column)) bool column_is_const = isColumnConst(*column);
{ if (column_is_const)
column_is_const = true;
column = &assert_cast<const ColumnConst &>(*column).getDataColumn(); column = &assert_cast<const ColumnConst &>(*column).getDataColumn();
}
const ColumnString & column_string = assert_cast<const ColumnString &>(*column); const ColumnString & column_string = assert_cast<const ColumnString &>(*column);
offsets = column_string.getOffsets().data(); offsets = column_string.getOffsets().data();
chars = column_string.getChars().data(); chars = column_string.getChars().data();
if (column_is_const)
get_key_holder_impl = [this](size_t /*row*/) { return StringRef(chars, offsets[0] - 1); };
else
get_key_holder_impl = [this](size_t row) { return StringRef(chars + offsets[row - 1], offsets[row] - offsets[row - 1] - 1); };
} }
auto getKeyHolder(ssize_t row, [[maybe_unused]] Arena & pool) const auto getKeyHolder(ssize_t row, [[maybe_unused]] Arena & pool) const
{ {
ssize_t pos = column_is_const ? 0 : row; StringRef key = get_key_holder_impl(row);
StringRef key(chars + offsets[pos - 1], offsets[pos] - offsets[pos - 1] - 1);
if constexpr (place_string_to_arena) if constexpr (place_string_to_arena)
{ {
return ArenaKeyHolder{key, pool}; return ArenaKeyHolder{key, pool};
@ -136,7 +144,7 @@ struct HashMethodFixedString
size_t n; size_t n;
const ColumnFixedString::Chars * chars; const ColumnFixedString::Chars * chars;
bool column_is_const = false; std::function<StringRef(size_t row)> get_key_holder_impl;
HashMethodFixedString(const ColumnRawPtrs & key_columns, const Sizes & /*key_sizes*/, const HashMethodContextPtr &) HashMethodFixedString(const ColumnRawPtrs & key_columns, const Sizes & /*key_sizes*/, const HashMethodContextPtr &)
{ {
@ -144,13 +152,15 @@ struct HashMethodFixedString
const ColumnFixedString & column_string = assert_cast<const ColumnFixedString &>(column); const ColumnFixedString & column_string = assert_cast<const ColumnFixedString &>(column);
n = column_string.getN(); n = column_string.getN();
chars = &column_string.getChars(); chars = &column_string.getChars();
column_is_const = isColumnConst(column); if (isColumnConst(column))
get_key_holder_impl = [this](size_t /*row*/) { return StringRef(&(*chars)[0], n); };
else
get_key_holder_impl = [this](size_t row) { return StringRef(&(*chars)[row * n], n); };
} }
auto getKeyHolder(size_t row, [[maybe_unused]] Arena & pool) const auto getKeyHolder(size_t row, [[maybe_unused]] Arena & pool) const
{ {
size_t pos = column_is_const ? 0 : row; StringRef key = get_key_holder_impl(row);
StringRef key(&(*chars)[pos * n], n);
if constexpr (place_string_to_arena) if constexpr (place_string_to_arena)
{ {