zuochunwei commented on a change in pull request #7972: URL: https://github.com/apache/incubator-doris/pull/7972#discussion_r805629745
########## File path: be/src/vec/exec/join/join_op.h ########## @@ -26,15 +26,15 @@ namespace doris::vectorized { struct RowRef { using SizeT = uint32_t; /// Do not use size_t cause of memory economy - const Block* block = nullptr; + // const Block* block = nullptr; SizeT row_num = 0; // Use in right join to mark row is visited // TODO: opt the varaible to use it only need bool visited = false; Review comment: use bitfield to make visited as the highest bit of row_num? maybe useful. ########## File path: be/src/vec/exec/join/vhash_join_node.cpp ########## @@ -292,8 +318,9 @@ struct ProcessHashTableProbe { std::vector<bool> same_to_prev; same_to_prev.reserve(1.2 * _batch_size); - int right_col_idx = _left_table_data_types.size(); - int right_col_len = _right_table_data_types.size(); + std::vector<uint32_t> _build_index; + _build_index.reserve(1.2 * _batch_size); Review comment: consider using stack array instead? ########## File path: be/src/vec/exec/join/vhash_join_node.cpp ########## @@ -217,49 +249,44 @@ struct ProcessHashTableProbe { // after probe data eof if (!_join_node->_is_right_semi_anti) { ++repeat_count; - for (size_t j = 0; j < right_col_len; ++j) { - auto& column = *mapped.block->get_by_position(j).column; - mcol[j + right_col_idx]->insert_from(column, mapped.row_num); - } + _build_index.emplace_back(mapped.row_num); } } else { for (auto it = mapped.begin(); it.ok(); ++it) { // right semi/anti join should dispose the data in hash table // after probe data eof if (!_join_node->_is_right_semi_anti) { ++repeat_count; - for (size_t j = 0; j < right_col_len; ++j) { - auto& column = *it->block->get_by_position(j).column; - // TODO: interface insert from cause serious performance problems - // when column is nullable. Try to make more effective way - mcol[j + right_col_idx]->insert_from(column, it->row_num); - } + _build_index.emplace_back(it->row_num); } it->visited = true; } } - } - } else if (_join_node->_match_all_probe || - _join_node->_join_op == TJoinOp::LEFT_ANTI_JOIN) { - ++repeat_count; - // only full outer / left outer need insert the data of right table - if (_join_node->_match_all_probe) { - for (size_t j = 0; j < right_col_len; ++j) { - DCHECK(mcol[j + right_col_idx]->is_nullable()); - mcol[j + right_col_idx]->insert_data(nullptr, 0); + } else if (_join_node->_match_all_probe) { + // only full outer / left outer need insert the data of right table + ++repeat_count; + for (size_t j = 0; j < _right_col_len; ++j) { + DCHECK(mcol[j + _right_col_idx]->is_nullable()); + mcol[j + _right_col_idx]->insert_data(nullptr, 0); } } } - items_counts[_probe_index++] = repeat_count; current_offset += repeat_count; - if (current_offset >= _batch_size) { break; } } - - for (int i = 0; i < right_col_idx; ++i) { + + // insert all match build rows + for (int i = 0; i < _right_col_len; i++) { + auto &column = *_build_block.get_by_position(i).column; + for (int j = 0; j < _build_index.size(); j++) { Review comment: use insert_indices_from() instead ########## File path: be/src/vec/exec/join/vhash_join_node.cpp ########## @@ -804,6 +838,10 @@ Status HashJoinNode::_hash_table_build(RuntimeState* state) { RETURN_IF_ERROR(child(1)->open(state)); SCOPED_TIMER(_build_timer); Block block; + MutableColumns columns(_right_table_data_types.size()); + for (int i = 0; i < _right_table_data_types.size(); i++) { + columns[i] = _right_table_data_types[i]->create_column(); Review comment: call reserve() here to avoid exlarging multi-times? ########## File path: be/src/vec/exec/join/join_op.h ########## @@ -115,7 +115,7 @@ struct RowRefList : RowRef { }; RowRefList() {} - RowRefList(const Block* block_, size_t row_num_) : RowRef(block_, row_num_) {} + RowRefList(size_t row_num_) : RowRef(row_num_) {} ForwardIterator begin() { return ForwardIterator(this); } Review comment: iterating RowRefList through ForwardIterator is slow, consider providing a interface to get all row_num list ########## File path: be/src/vec/exec/join/vhash_join_node.cpp ########## @@ -177,37 +180,66 @@ struct ProcessHashTableProbe { std::vector<uint32_t> items_counts(_probe_rows); auto& mcol = mutable_block.mutable_columns(); - - int right_col_idx = _join_node->_is_right_semi_anti ? 0 : _left_table_data_types.size(); - int right_col_len = _right_table_data_types.size(); int current_offset = 0; + std::vector<uint32_t> _build_index; + _build_index.reserve(1.2 * _batch_size); Review comment: why 1.2? ########## File path: be/src/vec/exec/join/vhash_join_node.cpp ########## @@ -177,37 +180,66 @@ struct ProcessHashTableProbe { std::vector<uint32_t> items_counts(_probe_rows); auto& mcol = mutable_block.mutable_columns(); - - int right_col_idx = _join_node->_is_right_semi_anti ? 0 : _left_table_data_types.size(); - int right_col_len = _right_table_data_types.size(); int current_offset = 0; + std::vector<uint32_t> _build_index; + _build_index.reserve(1.2 * _batch_size); for (; _probe_index < _probe_rows;) { - // ignore null rows if constexpr (ignore_null) { if ((*null_map)[_probe_index]) { items_counts[_probe_index++] = 0; continue; } } - int repeat_count = 0; - auto find_result = - (*null_map)[_probe_index] + if constexpr (is_inner_join) { + if (!(*null_map)[_probe_index]) { + auto find_result = key_getter.find_key(hash_table_ctx.hash_table, _probe_index, _arena); + + if (find_result.is_found()) { + auto& mapped = find_result.get_mapped(); + + if (mapped.get_row_count() == 1) { + ++repeat_count; + _build_index.emplace_back(mapped.row_num); + } else { + if (_probe_index + 2 < _probe_rows) + key_getter.prefetch(hash_table_ctx.hash_table, _probe_index + 2, _arena); + for (auto it = mapped.begin(); it.ok(); ++it) { + ++repeat_count; + _build_index.emplace_back(it->row_num); Review comment: if row_num stored in mapped as continuous array, we can just remember the row_num array’s address here. it's no need to copy one by one. ########## File path: be/src/vec/exec/join/vhash_join_node.cpp ########## @@ -316,10 +343,7 @@ struct ProcessHashTableProbe { for (auto it = mapped.begin(); it.ok(); ++it) { ++current_offset; - for (size_t j = 0; j < right_col_len; ++j) { - auto& column = *it->block->get_by_position(j).column; - mcol[j + right_col_idx]->insert_from(column, it->row_num); - } + _build_index.emplace_back(it->row_num); Review comment: increase current_offset += it.size() out of the loop -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org