dbms: JOINs: development [#METR-11370].

This commit is contained in:
Alexey Milovidov 2014-06-18 23:14:29 +04:00
parent d67b11211a
commit 2a25c8a4c0
2 changed files with 68 additions and 56 deletions

View File

@ -61,17 +61,7 @@ public:
void joinBlock(Block & block);
size_t size() const { return getTotalRowCount(); }
private:
ASTJoin::Kind kind;
ASTJoin::Strictness strictness;
/// Имена ключевых столбцов - по которым производится соединение.
const Names key_names;
/// Номера ключевых столбцов в "левой" таблице.
ColumnNumbers key_numbers_left;
/// Номера ключевых столбцов в "правой" таблице.
ColumnNumbers key_numbers_right;
/// Ссылка на строку в блоке.
struct RowRef
@ -92,6 +82,23 @@ private:
RowRefList(const Block * block_, size_t row_num_) : RowRef(block_, row_num_) {}
};
/** Разные структуры данных, которые могут использоваться для соединения.
*/
typedef HashMap<UInt64, RowRef> MapUInt64;
typedef HashMapWithSavedHash<StringRef, RowRef> MapString;
typedef HashMap<UInt128, RowRef, UInt128Hash> MapHashed;
private:
ASTJoin::Kind kind;
ASTJoin::Strictness strictness;
/// Имена ключевых столбцов - по которым производится соединение.
const Names key_names;
/// Номера ключевых столбцов в "левой" таблице.
ColumnNumbers key_numbers_left;
/// Номера ключевых столбцов в "правой" таблице.
ColumnNumbers key_numbers_right;
/** Блоки данных таблицы, с которой идёт соединение.
*/
Blocks blocks;
@ -107,12 +114,6 @@ private:
size_t rows_in_external_table;
bool only_external;
/** Разные структуры данных, которые могут использоваться для соединения.
*/
typedef HashMap<UInt64, RowRef> MapUInt64;
typedef HashMapWithSavedHash<StringRef, RowRef> MapString;
typedef HashMap<UInt128, RowRef, UInt128Hash> MapHashed;
/// Специализация для случая, когда есть один числовой ключ.
std::unique_ptr<MapUInt64> key64;
@ -157,7 +158,7 @@ private:
}
}
template <ASTJoin::Kind kind>
template <ASTJoin::Kind KIND>
void anyJoinBlock(Block & block);
/// Проверить не превышены ли допустимые размеры множества

View File

@ -55,6 +55,44 @@ bool Join::checkExternalSizeLimits() const
}
template <ASTJoin::Strictness STRICTNESS, typename Map>
struct Inserter
{
static void insert(Map & map, const typename Map::key_type & key, Block * stored_block, size_t i, Arena & pool);
};
template <typename Map>
struct Inserter<ASTJoin::Any, Map>
{
static void insert(Map & map, const typename Map::key_type & key, Block * stored_block, size_t i, Arena & pool)
{
typename Map::iterator it;
bool inserted;
map.emplace(key, it, inserted);
if (inserted)
new (&it->second) Join::RowRef(stored_block, i);
}
};
template <>
struct Inserter<ASTJoin::Any, Join::MapString>
{
static void insert(Join::MapString & map, const Join::MapString::key_type & key, Block * stored_block, size_t i, Arena & pool)
{
Join::MapString::iterator it;
bool inserted;
map.emplace(key, it, inserted);
if (inserted)
{
it->first.data = pool.insert(key.data, key.size);
new (&it->second) Join::RowRef(stored_block, i);
}
}
};
bool Join::insertFromBlock(const Block & block)
{
if (external_table)
@ -111,10 +149,10 @@ bool Join::insertFromBlock(const Block & block)
for (const auto & name : key_names)
stored_block->erase(stored_block->getPositionByName(name));
if (type == Set::KEY_64)
{
MapUInt64 & res = *key64;
typedef MapUInt64 Map;
Map & res = *key64;
const IColumn & column = *key_columns[0];
/// Для всех строчек
@ -122,18 +160,13 @@ bool Join::insertFromBlock(const Block & block)
{
/// Строим ключ
UInt64 key = column.get64(i);
MapUInt64::iterator it;
bool inserted;
res.emplace(key, it, inserted);
if (inserted)
new (&it->second) RowRef(stored_block, i);
Inserter<ASTJoin::Any, Map>::insert(res, key, stored_block, i, pool);
}
}
else if (type == Set::KEY_STRING)
{
MapString & res = *key_string;
typedef MapString Map;
Map & res = *key_string;
const IColumn & column = *key_columns[0];
if (const ColumnString * column_string = dynamic_cast<const ColumnString *>(&column))
@ -145,17 +178,8 @@ bool Join::insertFromBlock(const Block & block)
for (size_t i = 0; i < rows; ++i)
{
/// Строим ключ
StringRef ref(&data[i == 0 ? 0 : offsets[i - 1]], (i == 0 ? offsets[i] : (offsets[i] - offsets[i - 1])) - 1);
MapString::iterator it;
bool inserted;
res.emplace(ref, it, inserted);
if (inserted)
{
it->first.data = pool.insert(ref.data, ref.size);
new (&it->second) RowRef(stored_block, i);
}
StringRef key(&data[i == 0 ? 0 : offsets[i - 1]], (i == 0 ? offsets[i] : (offsets[i] - offsets[i - 1])) - 1);
Inserter<ASTJoin::Any, Map>::insert(res, key, stored_block, i, pool);
}
}
else if (const ColumnFixedString * column_string = dynamic_cast<const ColumnFixedString *>(&column))
@ -167,17 +191,8 @@ bool Join::insertFromBlock(const Block & block)
for (size_t i = 0; i < rows; ++i)
{
/// Строим ключ
StringRef ref(&data[i * n], n);
MapString::iterator it;
bool inserted;
res.emplace(ref, it, inserted);
if (inserted)
{
it->first.data = pool.insert(ref.data, ref.size);
new (&it->second) RowRef(stored_block, i);
}
StringRef key(&data[i * n], n);
Inserter<ASTJoin::Any, Map>::insert(res, key, stored_block, i, pool);
}
}
else
@ -185,7 +200,8 @@ bool Join::insertFromBlock(const Block & block)
}
else if (type == Set::HASHED)
{
MapHashed & res = *hashed;
typedef MapHashed Map;
Map & res = *hashed;
/// Для всех строчек
for (size_t i = 0; i < rows; ++i)
@ -194,12 +210,7 @@ bool Join::insertFromBlock(const Block & block)
? pack128(i, keys_size, key_columns, key_sizes)
: hash128(i, keys_size, key_columns);
MapHashed::iterator it;
bool inserted;
res.emplace(key, it, inserted);
if (inserted)
new (&it->second) RowRef(stored_block, i);
Inserter<ASTJoin::Any, Map>::insert(res, key, stored_block, i, pool);
}
}
else