OmniSciDB  f17484ade4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
QueryHint.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 
17 #ifndef OMNISCI_QUERYHINT_H
18 #define OMNISCI_QUERYHINT_H
19 
20 #include <algorithm>
21 #include <optional>
22 
23 #include <boost/algorithm/string.hpp>
24 
26 
27 // we expect query hint enum val starts with zero,
28 // and let remaining enum value to be auto-incremented
29 enum QueryHint {
30  kCpuMode = 0,
55  kHintCount, // should be at the last elem before INVALID enum value to count #
56  // supported hints correctly
57  kInvalidHint // this should be the last elem of this enum
58 };
59 
60 static const std::unordered_map<std::string, QueryHint> SupportedQueryHints = {
61  {"cpu_mode", QueryHint::kCpuMode},
62  {"columnar_output", QueryHint::kColumnarOutput},
63  {"rowwise_output", QueryHint::kRowwiseOutput},
64  {"bbox_intersect_bucket_threshold", QueryHint::kBBoxIntersectBucketThreshold},
65  {"bbox_intersect_max_size", QueryHint::kBBoxIntersectMaxSize},
66  {"bbox_intersect_allow_gpu_build", QueryHint::kBBoxIntersectAllowGpuBuild},
67  {"bbox_intersect_no_cache", QueryHint::kBBoxIntersectNoCache},
68  {"bbox_intersect_keys_per_bin", QueryHint::kBBoxIntersectKeysPerBin},
69  {"keep_result", QueryHint::kKeepResult},
70  {"keep_table_function_result", QueryHint::kKeepTableFuncResult},
71  {"aggregate_tree_fanout", QueryHint::kAggregateTreeFanout},
72  {"cuda_block_size", QueryHint::kCudaBlockSize},
73  {"cuda_grid_size_multiplier", QueryHint::kCudaGridSize},
74  {"cuda_opt_block_and_grid_sizes", kOptCudaBlockAndGridSizes},
75  {"watchdog", QueryHint::kWatchdog},
76  {"dynamic_watchdog", QueryHint::kDynamicWatchdog},
77  {"watchdog_off", QueryHint::kWatchdogOff},
78  {"dynamic_watchdog_off", QueryHint::kDynamicWatchdogOff},
79  {"query_time_limit", QueryHint::kQueryTimeLimit},
80  {"allow_loop_join", QueryHint::kAllowLoopJoin},
81  {"disable_loop_join", QueryHint::kDisableLoopJoin},
82  {"loop_join_inner_table_max_num_rows", QueryHint::kLoopJoinInnerTableMaxNumRows},
83  {"max_join_hashtable_size", QueryHint::kMaxJoinHashTableSize},
84  {"force_baseline_hash_join", QueryHint::kforceBaselineHashJoin},
85  {"force_one_to_many_hash_join", QueryHint::kforceOneToManyHashJoin}};
86 
89  std::string hint_name;
90 
91  HintIdentifier(bool global_hint, const std::string& hint_name)
92  : global_hint(global_hint), hint_name(hint_name){};
93 };
94 
96  // this class represents parsed query hint's specification
97  // our query AST analyzer translates query hint string to understandable form which we
98  // called "ExplainedQueryHint"
99  public:
100  // default constructor used for deserialization only
103  , global_hint_{false}
104  , is_marker_{false}
105  , has_kv_type_options_{false} {}
106 
108  bool global_hint,
109  bool is_marker,
110  bool has_kv_type_options)
111  : hint_(hint)
112  , global_hint_(global_hint)
113  , is_marker_(is_marker)
114  , has_kv_type_options_(has_kv_type_options) {}
115 
117  bool global_hint,
118  bool is_marker,
119  bool has_kv_type_options,
120  std::vector<std::string>& list_options)
121  : hint_(hint)
122  , global_hint_(global_hint)
123  , is_marker_(is_marker)
124  , has_kv_type_options_(has_kv_type_options)
125  , list_options_(std::move(list_options)) {}
126 
128  bool global_hint,
129  bool is_marker,
130  bool has_kv_type_options,
131  std::unordered_map<std::string, std::string>& kv_options)
132  : hint_(hint)
133  , global_hint_(global_hint)
134  , is_marker_(is_marker)
135  , has_kv_type_options_(has_kv_type_options)
136  , kv_options_(std::move(kv_options)) {}
137 
138  void setListOptions(std::vector<std::string>& list_options) {
139  list_options_ = list_options;
140  }
141 
142  void setKVOptions(std::unordered_map<std::string, std::string>& kv_options) {
143  kv_options_ = kv_options;
144  }
145 
146  void setInheritPaths(std::vector<int>& interit_paths) {
147  inherit_paths_ = interit_paths;
148  }
149 
150  const std::vector<std::string>& getListOptions() const { return list_options_; }
151 
152  const std::vector<int>& getInteritPath() const { return inherit_paths_; }
153 
154  const std::unordered_map<std::string, std::string>& getKVOptions() const {
155  return kv_options_;
156  }
157 
158  const QueryHint getHint() const { return hint_; }
159 
160  bool isGlobalHint() const { return global_hint_; }
161 
162  bool hasOptions() const { return is_marker_; }
163 
164  bool hasKvOptions() const { return has_kv_type_options_; }
165 
166  private:
168  // Set true if this hint affects globally
169  // Otherwise it just affects the node which this hint is included (aka table hint)
171  // set true if this has no extra options (neither list_options nor kv_options)
173  // Set true if it is not a marker and has key-value type options
174  // Otherwise (it is not a marker but has list type options), we set this be false
176  std::vector<int> inherit_paths_; // currently not used
177  std::vector<std::string> list_options_;
178  std::unordered_map<std::string, std::string> kv_options_;
179 };
180 
182  // for each query hint, we first translate the raw query hint info
183  // to understandable form called "ExplainedQueryHint"
184  // and we get all necessary info from it and organize it into "RegisteredQueryHint"
185  // so by using "RegisteredQueryHint", we can know and access which query hint is
186  // registered and its detailed info such as the hint's parameter values given by user
187  // NOTE: after changing query hint fields, we "SHOULD" also update the corresponding
188  // "QueryHintSerializer" accordingly
190  : cpu_mode(false)
193  , keep_result(false)
195  , watchdog(std::nullopt)
196  , dynamic_watchdog(std::nullopt)
197  , query_time_limit(0)
198  , cuda_block_size(0)
202  , bbox_intersect_bucket_threshold(std::numeric_limits<double>::max())
207  , use_loop_join(std::nullopt)
209  , max_join_hash_table_size(std::numeric_limits<size_t>::max())
213 
215  CHECK_EQ(registered_hint.size(), global_hints.registered_hint.size());
216  // apply registered global hint to the local hint if necessary
217  // we prioritize global hint when both side of hints are enabled simultaneously
218  RegisteredQueryHint updated_query_hints(*this);
219 
220  constexpr int num_hints = static_cast<int>(QueryHint::kHintCount);
221  for (int i = 0; i < num_hints; ++i) {
222  if (global_hints.registered_hint.at(i)) {
223  updated_query_hints.registered_hint.at(i) = true;
224  switch (static_cast<QueryHint>(i)) {
225  case QueryHint::kCpuMode:
226  updated_query_hints.cpu_mode = true;
227  break;
229  updated_query_hints.columnar_output = true;
230  break;
232  updated_query_hints.rowwise_output = true;
233  break;
235  updated_query_hints.cuda_block_size = global_hints.cuda_block_size;
236  break;
238  updated_query_hints.cuda_grid_size_multiplier =
239  global_hints.cuda_grid_size_multiplier;
240  break;
242  updated_query_hints.opt_cuda_grid_and_block_size = true;
243  break;
245  updated_query_hints.bbox_intersect_bucket_threshold =
246  global_hints.bbox_intersect_bucket_threshold;
247  break;
249  updated_query_hints.bbox_intersect_max_size =
250  global_hints.bbox_intersect_max_size;
251  break;
253  updated_query_hints.bbox_intersect_allow_gpu_build = true;
254  break;
256  updated_query_hints.bbox_intersect_no_cache = true;
257  break;
259  updated_query_hints.bbox_intersect_keys_per_bin =
260  global_hints.bbox_intersect_keys_per_bin;
261  break;
263  updated_query_hints.keep_result = global_hints.keep_result;
264  break;
266  updated_query_hints.keep_table_function_result =
267  global_hints.keep_table_function_result;
268  break;
270  updated_query_hints.aggregate_tree_fanout =
271  global_hints.aggregate_tree_fanout;
272  break;
275  updated_query_hints.watchdog = global_hints.watchdog;
276  break;
279  updated_query_hints.dynamic_watchdog = global_hints.dynamic_watchdog;
280  break;
282  updated_query_hints.query_time_limit = global_hints.query_time_limit;
283  break;
286  updated_query_hints.use_loop_join = global_hints.use_loop_join;
287  break;
289  updated_query_hints.loop_join_inner_table_max_num_rows =
291  break;
293  updated_query_hints.max_join_hash_table_size =
294  global_hints.max_join_hash_table_size;
295  break;
297  updated_query_hints.force_baseline_hash_join =
298  global_hints.force_baseline_hash_join;
299  break;
301  updated_query_hints.force_one_to_many_hash_join =
302  global_hints.force_one_to_many_hash_join;
303  break;
304  default:
305  UNREACHABLE();
306  }
307  }
308  }
309  return updated_query_hints;
310  }
311 
312  // general query execution
313  bool cpu_mode;
318  std::optional<bool> watchdog;
319  std::optional<bool> dynamic_watchdog;
321 
322  // control CUDA behavior
326 
327  // window function framing
329 
330  // bbox_intersect hash join
331  double bbox_intersect_bucket_threshold; // defined in
332  // "BoundingBoxIntersectJoinHashTable.h"
337 
338  // generic hash join
339  std::optional<bool> use_loop_join;
344 
345  std::vector<bool> registered_hint;
346 
348 
349  public:
350  static QueryHint translateQueryHint(const std::string& hint_name) {
351  const auto lowered_hint_name = boost::algorithm::to_lower_copy(hint_name);
352  auto it = SupportedQueryHints.find(lowered_hint_name);
353  return it == SupportedQueryHints.end() ? QueryHint::kInvalidHint : it->second;
354  }
355 
356  bool isAnyQueryHintDelivered() const {
357  const auto identity = [](const bool b) { return b; };
358  return std::any_of(registered_hint.begin(), registered_hint.end(), identity);
359  }
360 
361  void registerHint(const QueryHint hint) {
362  const auto hint_class = static_cast<int>(hint);
363  registered_hint.at(hint_class) = true;
364  }
365 
366  bool isHintRegistered(const QueryHint hint) const {
367  const auto hint_class = static_cast<int>(hint);
368  return registered_hint.at(hint_class);
369  }
370 };
371 
372 // a map from hint_name to its detailed info
373 using Hints = std::unordered_map<QueryHint, ExplainedQueryHint>;
374 
375 #endif // OMNISCI_QUERYHINT_H
std::unordered_map< std::string, std::string > kv_options_
Definition: QueryHint.h:178
#define CHECK_EQ(x, y)
Definition: Logger.h:301
bool isGlobalHint() const
Definition: QueryHint.h:160
double bbox_intersect_keys_per_bin
Definition: QueryHint.h:336
const std::vector< int > & getInteritPath() const
Definition: QueryHint.h:152
const std::unordered_map< std::string, std::string > & getKVOptions() const
Definition: QueryHint.h:154
#define UNREACHABLE()
Definition: Logger.h:338
double g_bbox_intersect_target_entries_per_bin
Definition: Execute.cpp:109
void setListOptions(std::vector< std::string > &list_options)
Definition: QueryHint.h:138
std::optional< bool > dynamic_watchdog
Definition: QueryHint.h:319
double cuda_grid_size_multiplier
Definition: QueryHint.h:324
size_t cuda_block_size
Definition: QueryHint.h:323
ExplainedQueryHint(QueryHint hint, bool global_hint, bool is_marker, bool has_kv_type_options)
Definition: QueryHint.h:107
std::vector< bool > registered_hint
Definition: QueryHint.h:345
void setKVOptions(std::unordered_map< std::string, std::string > &kv_options)
Definition: QueryHint.h:142
unsigned g_trivial_loop_join_threshold
Definition: Execute.cpp:90
ExplainedQueryHint(QueryHint hint, bool global_hint, bool is_marker, bool has_kv_type_options, std::vector< std::string > &list_options)
Definition: QueryHint.h:116
size_t max_join_hash_table_size
Definition: QueryHint.h:341
bool opt_cuda_grid_and_block_size
Definition: QueryHint.h:325
bool hasKvOptions() const
Definition: QueryHint.h:164
bool keep_table_function_result
Definition: QueryHint.h:317
size_t query_time_limit
Definition: QueryHint.h:320
static const std::unordered_map< std::string, QueryHint > SupportedQueryHints
Definition: QueryHint.h:60
static QueryHint translateQueryHint(const std::string &hint_name)
Definition: QueryHint.h:350
std::vector< std::string > list_options_
Definition: QueryHint.h:177
double bbox_intersect_bucket_threshold
Definition: QueryHint.h:331
void registerHint(const QueryHint hint)
Definition: QueryHint.h:361
bool hasOptions() const
Definition: QueryHint.h:162
HintIdentifier(bool global_hint, const std::string &hint_name)
Definition: QueryHint.h:91
std::optional< bool > watchdog
Definition: QueryHint.h:318
static RegisteredQueryHint defaults()
Definition: QueryHint.h:347
bool isHintRegistered(const QueryHint hint) const
Definition: QueryHint.h:366
std::unordered_map< QueryHint, ExplainedQueryHint > Hints
Definition: QueryHint.h:373
QueryHint
Definition: QueryHint.h:29
size_t bbox_intersect_max_size
Definition: QueryHint.h:333
bool force_baseline_hash_join
Definition: QueryHint.h:342
bool bbox_intersect_no_cache
Definition: QueryHint.h:335
std::optional< bool > use_loop_join
Definition: QueryHint.h:339
RegisteredQueryHint operator||(const RegisteredQueryHint &global_hints) const
Definition: QueryHint.h:214
bool g_enable_watchdog false
Definition: Execute.cpp:80
bool global_hint
Definition: QueryHint.h:88
size_t loop_join_inner_table_max_num_rows
Definition: QueryHint.h:340
bool bbox_intersect_allow_gpu_build
Definition: QueryHint.h:334
std::vector< int > inherit_paths_
Definition: QueryHint.h:176
bool has_kv_type_options_
Definition: QueryHint.h:175
bool any_of(std::vector< Analyzer::Expr * > const &target_exprs)
QueryHint hint_
Definition: QueryHint.h:167
size_t aggregate_tree_fanout
Definition: QueryHint.h:328
const QueryHint getHint() const
Definition: QueryHint.h:158
std::string hint_name
Definition: QueryHint.h:89
const std::vector< std::string > & getListOptions() const
Definition: QueryHint.h:150
void setInheritPaths(std::vector< int > &interit_paths)
Definition: QueryHint.h:146
ExplainedQueryHint(QueryHint hint, bool global_hint, bool is_marker, bool has_kv_type_options, std::unordered_map< std::string, std::string > &kv_options)
Definition: QueryHint.h:127
bool isAnyQueryHintDelivered() const
Definition: QueryHint.h:356
bool force_one_to_many_hash_join
Definition: QueryHint.h:343
size_t g_bbox_intersect_max_table_size_bytes
Definition: Execute.cpp:108