OmniSciDB  72c90bc290
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PerfectJoinHashTable.h
Go to the documentation of this file.
1 /*
2  * Copyright 2022 HEAVY.AI, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
23 #pragma once
24 
25 #include "Analyzer/Analyzer.h"
27 #include "DataMgr/Chunk/Chunk.h"
37 
38 #include <llvm/IR/Value.h>
39 
40 #ifdef HAVE_CUDA
41 #include <cuda.h>
42 #endif
43 #include <functional>
44 #include <memory>
45 #include <mutex>
46 #include <stdexcept>
47 
49 
51  public:
53  static std::shared_ptr<PerfectJoinHashTable> getInstance(
54  const std::shared_ptr<Analyzer::BinOper> qual_bin_oper,
55  const std::vector<InputTableInfo>& query_infos,
56  const Data_Namespace::MemoryLevel memory_level,
57  const JoinType join_type,
58  const HashType preferred_hash_type,
59  const int device_count,
60  ColumnCacheMap& column_cache,
61  Executor* executor,
62  const HashTableBuildDagMap& hashtable_build_dag_map,
63  const RegisteredQueryHint& query_hints,
64  const TableIdToNodeMap& table_id_to_node_map);
65 
66  std::string toString(const ExecutorDeviceType device_type,
67  const int device_id = 0,
68  bool raw = false) const override;
69 
70  std::set<DecodedJoinHashBufferEntry> toSet(const ExecutorDeviceType device_type,
71  const int device_id) const override;
72 
73  llvm::Value* codegenSlot(const CompilationOptions&, const size_t) override;
74 
76  const size_t) override;
77 
78  shared::TableKey getInnerTableId() const noexcept override {
79  return col_var_->getTableKey();
80  };
81 
82  int getInnerTableRteIdx() const noexcept override {
83  return col_var_.get()->get_rte_idx();
84  };
85 
86  HashType getHashType() const noexcept override { return hash_type_; }
87 
88  Data_Namespace::MemoryLevel getMemoryLevel() const noexcept override {
89  return memory_level_;
90  };
91 
92  int getDeviceCount() const noexcept override { return device_count_; };
93 
94  size_t offsetBufferOff() const noexcept override;
95 
96  size_t countBufferOff() const noexcept override;
97 
98  size_t payloadBufferOff() const noexcept override;
99 
100  std::string getHashJoinType() const final { return "Perfect"; }
101 
104  return hash_table_cache_.get();
105  }
108  return hash_table_layout_cache_.get();
109  }
110 
111  static void invalidateCache() {
113  hash_table_layout_cache_->clearCache();
114 
116  hash_table_cache_->clearCache();
117  }
118 
119  static void markCachedItemAsDirty(size_t table_key) {
122  auto candidate_table_keys =
123  hash_table_cache_->getMappedQueryPlanDagsWithTableKey(table_key);
124  if (candidate_table_keys.has_value()) {
125  hash_table_layout_cache_->markCachedItemAsDirty(
126  table_key,
127  *candidate_table_keys,
130  hash_table_cache_->markCachedItemAsDirty(table_key,
131  *candidate_table_keys,
134  }
135  }
136 
138 
140 
143  }
144 
146 
147  private:
148  // Equijoin API
150  const std::vector<ColumnsForDevice>& columns_per_device) const;
151 
153  const std::vector<Fragmenter_Namespace::FragmentInfo>& fragments,
154  const int device_id,
155  DeviceAllocator* dev_buff_owner);
156 
157  void reifyForDevice(const ChunkKey& hash_table_key,
158  const ColumnsForDevice& columns_for_device,
159  const HashType layout,
160  const int device_id,
161  const logger::ThreadLocalIds);
162 
163  int initHashTableForDevice(const ChunkKey& chunk_key,
164  const JoinColumn& join_column,
165  const InnerOuter& cols,
166  const HashType layout,
167  const Data_Namespace::MemoryLevel effective_memory_level,
168  const int device_id);
169 
171  const std::vector<InnerOuter>& inner_outer_pairs) const;
172 
173  std::vector<InnerOuter> inner_outer_pairs_;
174 
175  PerfectJoinHashTable(const std::shared_ptr<Analyzer::BinOper> qual_bin_oper,
176  const Analyzer::ColumnVar* col_var,
177  const std::vector<InputTableInfo>& query_infos,
178  const Data_Namespace::MemoryLevel memory_level,
179  const JoinType join_type,
180  const HashType preferred_hash_type,
181  const ExpressionRange& col_range,
182  const ExpressionRange& rhs_source_col_range,
183  const BucketizedHashEntryInfo hash_entry_info,
184  ColumnCacheMap& column_cache,
185  Executor* executor,
186  const int device_count,
187  const RegisteredQueryHint& query_hints,
188  const HashTableBuildDagMap& hashtable_build_dag_map,
189  const TableIdToNodeMap& table_id_to_node_map,
190  const size_t rowid_size,
191  const InnerOuterStringOpInfos& inner_outer_string_op_infos = {})
192  : qual_bin_oper_(qual_bin_oper)
193  , join_type_(join_type)
194  , col_var_(std::dynamic_pointer_cast<Analyzer::ColumnVar>(col_var->deep_copy()))
195  , query_infos_(query_infos)
196  , memory_level_(memory_level)
197  , hash_type_(preferred_hash_type)
198  , col_range_(col_range)
199  , rhs_source_col_range_(rhs_source_col_range)
200  , hash_entry_info_(hash_entry_info)
201  , executor_(executor)
202  , column_cache_(column_cache)
203  , device_count_(device_count)
204  , query_hints_(query_hints)
205  , needs_dict_translation_(false)
206  , hashtable_build_dag_map_(hashtable_build_dag_map)
207  , table_id_to_node_map_(table_id_to_node_map)
208  , inner_outer_string_op_infos_(inner_outer_string_op_infos)
209  , rowid_size_(rowid_size) {
213  }
214 
215  ChunkKey genChunkKey(const std::vector<Fragmenter_Namespace::FragmentInfo>& fragments,
216  const Analyzer::Expr* outer_col,
217  const Analyzer::ColumnVar* inner_col) const;
218 
219  void reify();
220  std::shared_ptr<PerfectHashTable> initHashTableOnCpuFromCache(
221  QueryPlanHash key,
222  CacheItemType item_type,
223  DeviceIdentifier device_identifier);
225  CacheItemType item_type,
226  std::shared_ptr<PerfectHashTable> hashtable_ptr,
227  DeviceIdentifier device_identifier,
228  size_t hashtable_building_time);
229 
230  const InputTableInfo& getInnerQueryInfo(const Analyzer::ColumnVar* inner_col) const;
231 
232  size_t shardCount() const;
233 
234  llvm::Value* codegenHashTableLoad(const size_t table_idx);
235 
236  std::vector<llvm::Value*> getHashJoinArgs(llvm::Value* hash_ptr,
237  llvm::Value* key_lvs,
238  const Analyzer::Expr* key_col,
239  const int shard_count,
240  const CompilationOptions& co);
241 
242  bool isBitwiseEq() const override;
243 
244  size_t getComponentBufferSize() const noexcept override;
245 
246  HashTable* getHashTableForDevice(const size_t device_id) const;
247 
248  void copyCpuHashTableToGpu(std::shared_ptr<PerfectHashTable>& cpu_hash_table,
249  const PerfectHashTableEntryInfo hash_table_entry_info,
250  const int device_id,
251  Data_Namespace::DataMgr* data_mgr);
252 
259  const size_t num_elements;
260  const SQLOps optype;
262  };
263 
266  auto hash = boost::hash_value(::toString(info.chunk_key));
267  boost::hash_combine(hash, info.inner_col->toString());
268  if (info.inner_col->get_type_info().is_string()) {
269  boost::hash_combine(hash, info.outer_col->toString());
270  }
271  boost::hash_combine(hash, ::toString(info.inner_outer_string_op_infos));
272  boost::hash_combine(hash, info.col_range.toString());
273  boost::hash_combine(hash, info.num_elements);
274  boost::hash_combine(hash, info.optype);
275  boost::hash_combine(hash, info.join_type);
276  return hash;
277  }
278 
279  std::shared_ptr<Analyzer::BinOper> qual_bin_oper_;
281  std::shared_ptr<Analyzer::ColumnVar> col_var_;
282  const std::vector<InputTableInfo>& query_infos_;
291  Executor* executor_;
293  const int device_count_;
297  // per-device cache key to cover hash table for sharded table
298  std::vector<QueryPlanHash> hashtable_cache_key_;
300  std::unordered_set<size_t> table_keys_;
303  const size_t rowid_size_;
304 
305  static std::unique_ptr<HashtableRecycler> hash_table_cache_;
306  static std::unique_ptr<HashingSchemeRecycler> hash_table_layout_cache_;
307 };
308 
310  const InnerOuter& inner_outer_col_pair,
311  const InnerOuterStringOpInfos& inner_outer_string_op_infos,
312  const Executor* executor);
313 
315  const Data_Namespace::MemoryLevel memory_level,
316  const bool needs_dict_translation) {
317  if (needs_dict_translation) {
319  }
320  return memory_level;
321 }
322 
323 std::vector<Fragmenter_Namespace::FragmentInfo> only_shards_for_device(
324  const std::vector<Fragmenter_Namespace::FragmentInfo>& fragments,
325  const int device_id,
326  const int device_count);
327 
329  const shared::TableKey& inner_table_key,
330  const std::vector<InputTableInfo>& query_infos);
331 
332 size_t get_entries_per_device(const size_t total_entries,
333  const size_t shard_count,
334  const size_t device_count,
335  const Data_Namespace::MemoryLevel memory_level);
Defines data structures for the semantic analysis phase of query processing.
llvm::Value * codegenHashTableLoad(const size_t table_idx)
BucketizedHashEntryInfo hash_entry_info_
std::string toString() const
std::vector< int > ChunkKey
Definition: types.h:36
size_t DeviceIdentifier
Definition: DataRecycler.h:129
JoinType
Definition: sqldefs.h:174
Data_Namespace::MemoryLevel getEffectiveMemoryLevel(const std::vector< InnerOuter > &inner_outer_pairs) const
ExpressionRange rhs_source_col_range_
std::pair< const Analyzer::ColumnVar *, const Analyzer::Expr * > InnerOuter
Definition: HashJoin.h:105
size_t getNormalizedHashEntryCount() const
const Data_Namespace::MemoryLevel memory_level_
size_t getComponentBufferSize() const noexceptoverride
std::shared_ptr< Analyzer::BinOper > qual_bin_oper_
PerfectJoinHashTable(const std::shared_ptr< Analyzer::BinOper > qual_bin_oper, const Analyzer::ColumnVar *col_var, const std::vector< InputTableInfo > &query_infos, const Data_Namespace::MemoryLevel memory_level, const JoinType join_type, const HashType preferred_hash_type, const ExpressionRange &col_range, const ExpressionRange &rhs_source_col_range, const BucketizedHashEntryInfo hash_entry_info, ColumnCacheMap &column_cache, Executor *executor, const int device_count, const RegisteredQueryHint &query_hints, const HashTableBuildDagMap &hashtable_build_dag_map, const TableIdToNodeMap &table_id_to_node_map, const size_t rowid_size, const InnerOuterStringOpInfos &inner_outer_string_op_infos={})
std::mutex str_proxy_translation_mutex_
ChunkKey genChunkKey(const std::vector< Fragmenter_Namespace::FragmentInfo > &fragments, const Analyzer::Expr *outer_col, const Analyzer::ColumnVar *inner_col) const
const TableIdToNodeMap table_id_to_node_map_
SQLOps
Definition: sqldefs.h:28
size_t offsetBufferOff() const noexceptoverride
std::vector< std::shared_ptr< HashTable > > hash_tables_for_device_
Definition: HashJoin.h:377
HashTableBuildDagMap hashtable_build_dag_map_
Data_Namespace::MemoryLevel get_effective_memory_level(const Data_Namespace::MemoryLevel memory_level, const bool needs_dict_translation)
const InputTableInfo & get_inner_query_info(const shared::TableKey &inner_table_key, const std::vector< InputTableInfo > &query_infos)
int getDeviceCount() const noexceptoverride
const InputTableInfo & getInnerQueryInfo(const Analyzer::ColumnVar *inner_col) const
size_t payloadBufferOff() const noexceptoverride
ColumnsForDevice fetchColumnsForDevice(const std::vector< Fragmenter_Namespace::FragmentInfo > &fragments, const int device_id, DeviceAllocator *dev_buff_owner)
std::shared_ptr< Analyzer::Expr > deep_copy() const override
Definition: Analyzer.cpp:66
std::shared_ptr< PerfectHashTable > initHashTableOnCpuFromCache(QueryPlanHash key, CacheItemType item_type, DeviceIdentifier device_identifier)
bool needs_dictionary_translation(const std::vector< InnerOuter > &inner_outer_pairs, const std::vector< InnerOuterStringOpInfos > &inner_outer_string_op_infos_pairs, const Executor *executor)
#define CHECK_GT(x, y)
Definition: Logger.h:305
HashType getHashType() const noexceptoverride
ExecutorDeviceType
HashtableCacheMetaInfo hashtable_cache_meta_info_
static std::unique_ptr< HashtableRecycler > hash_table_cache_
std::string getHashJoinType() const final
shared::TableKey getInnerTableId() const noexceptoverride
std::unordered_map< size_t, HashTableBuildDag > HashTableBuildDagMap
CacheItemType
Definition: DataRecycler.h:38
void reifyForDevice(const ChunkKey &hash_table_key, const ColumnsForDevice &columns_for_device, const HashType layout, const int device_id, const logger::ThreadLocalIds)
static HashtableRecycler * getHashTableCache()
std::string toString() const override
Definition: Analyzer.cpp:2717
std::vector< Fragmenter_Namespace::FragmentInfo > only_shards_for_device(const std::vector< Fragmenter_Namespace::FragmentInfo > &fragments, const int device_id, const int device_count)
bool isOneToOneHashPossible(const std::vector< ColumnsForDevice > &columns_per_device) const
static HashingSchemeRecycler * getHashingSchemeCache()
const RegisteredQueryHint & getRegisteredQueryHint()
const SQLTypeInfo & get_type_info() const
Definition: Analyzer.h:79
std::vector< llvm::Value * > getHashJoinArgs(llvm::Value *hash_ptr, llvm::Value *key_lvs, const Analyzer::Expr *key_col, const int shard_count, const CompilationOptions &co)
std::vector< InnerOuter > inner_outer_pairs_
static std::unique_ptr< HashingSchemeRecycler > hash_table_layout_cache_
std::unordered_map< shared::TableKey, const RelAlgNode * > TableIdToNodeMap
static QueryPlanHash getAlternativeCacheKey(AlternativeCacheKeyForPerfectHashJoin &info)
const std::vector< InputTableInfo > & query_infos_
void putHashTableOnCpuToCache(QueryPlanHash key, CacheItemType item_type, std::shared_ptr< PerfectHashTable > hashtable_ptr, DeviceIdentifier device_identifier, size_t hashtable_building_time)
std::string toString(const ExecutorDeviceType device_type, const int device_id=0, bool raw=false) const override
size_t getNormalizedHashEntryCount() const
ColumnCacheMap & column_cache_
size_t get_entries_per_device(const size_t total_entries, const size_t shard_count, const size_t device_count, const Data_Namespace::MemoryLevel memory_level)
std::shared_ptr< Analyzer::ColumnVar > col_var_
RegisteredQueryHint query_hints_
BucketizedHashEntryInfo getHashEntryInfo() const
std::unordered_map< shared::TableKey, std::unordered_map< int, std::shared_ptr< const ColumnarResults >>> ColumnCacheMap
size_t QueryPlanHash
static std::shared_ptr< PerfectJoinHashTable > getInstance(const std::shared_ptr< Analyzer::BinOper > qual_bin_oper, const std::vector< InputTableInfo > &query_infos, const Data_Namespace::MemoryLevel memory_level, const JoinType join_type, const HashType preferred_hash_type, const int device_count, ColumnCacheMap &column_cache, Executor *executor, const HashTableBuildDagMap &hashtable_build_dag_map, const RegisteredQueryHint &query_hints, const TableIdToNodeMap &table_id_to_node_map)
Make hash table from an in-flight SQL query&#39;s parse tree etc.
const InnerOuterStringOpInfos inner_outer_string_op_infos_
llvm::Value * codegenSlot(const CompilationOptions &, const size_t) override
std::size_t hash_value(RexAbstractInput const &rex_ab_input)
Definition: RelAlgDag.cpp:3525
ExpressionRangeType getType() const
std::pair< std::vector< StringOps_Namespace::StringOpInfo >, std::vector< StringOps_Namespace::StringOpInfo >> InnerOuterStringOpInfos
Definition: HashJoin.h:107
#define CHECK(condition)
Definition: Logger.h:291
size_t countBufferOff() const noexceptoverride
int initHashTableForDevice(const ChunkKey &chunk_key, const JoinColumn &join_column, const InnerOuter &cols, const HashType layout, const Data_Namespace::MemoryLevel effective_memory_level, const int device_id)
void copyCpuHashTableToGpu(std::shared_ptr< PerfectHashTable > &cpu_hash_table, const PerfectHashTableEntryInfo hash_table_entry_info, const int device_id, Data_Namespace::DataMgr *data_mgr)
std::vector< QueryPlanHash > hashtable_cache_key_
bool is_string() const
Definition: sqltypes.h:559
HashTable * getHashTableForDevice(const size_t device_id) const
Data_Namespace::MemoryLevel getMemoryLevel() const noexceptoverride
static constexpr DeviceIdentifier CPU_DEVICE_IDENTIFIER
Definition: DataRecycler.h:136
std::set< DecodedJoinHashBufferEntry > toSet(const ExecutorDeviceType device_type, const int device_id) const override
HashType
Definition: HashTable.h:19
static void markCachedItemAsDirty(size_t table_key)
const StringDictionaryProxy::IdMap * str_proxy_translation_map_
std::unordered_set< size_t > table_keys_
HashJoinMatchingSet codegenMatchingSet(const CompilationOptions &, const size_t) override
bool isBitwiseEq() const override
int getInnerTableRteIdx() const noexceptoverride