Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 3.9k
[Feature](Variant) support variant load#24554
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
2380730456e3a8647d938ea484fae8fe2aae698efbf32a5b7c52d069File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -21,6 +21,7 @@ | ||
| #include "olap/tablet_schema_cache.h" | ||
| #include "util/doris_metrics.h" | ||
| #include "vec/common/schema_util.h" | ||
| namespace doris { | ||
| using namespace ErrorCode; | ||
| @@ -65,4 +66,14 @@ void BaseTablet::update_max_version_schema(const TabletSchemaSPtr& tablet_schema | ||
| } | ||
| } | ||
| void BaseTablet::update_by_least_common_schema(const TabletSchemaSPtr& update_schema) { | ||
Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: method 'update_by_least_common_schema' can be made static [readability-convert-member-functions-to-static] be/src/olap/base_tablet.h:67: - void update_by_least_common_schema(const TabletSchemaSPtr& update_schema);+ static void update_by_least_common_schema(const TabletSchemaSPtr& update_schema); | ||
| std::lock_guard wrlock(_meta_lock); | ||
| auto final_schema = std::make_shared<TabletSchema>(); | ||
| CHECK(_max_version_schema->schema_version() >= update_schema->schema_version()); | ||
| vectorized::schema_util::get_least_common_schema({_max_version_schema, update_schema}, | ||
| final_schema); | ||
| _max_version_schema = final_schema; | ||
| VLOG_DEBUG << "dump updated tablet schema: " << final_schema->dump_structure(); | ||
| } | ||
| } /* namespace doris */ | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -54,7 +54,7 @@ | ||
| #include "util/time.h" | ||
| #include "vec/columns/column.h" | ||
| #include "vec/columns/column_object.h" | ||
| #include "vec/common/schema_util.h" // LocalSchemaChangeRecorder | ||
| #include "vec/common/schema_util.h" // variant column | ||
| #include "vec/core/block.h" | ||
| #include "vec/data_types/data_type_factory.hpp" | ||
| @@ -123,8 +123,6 @@ Status BetaRowsetWriter::init(const RowsetWriterContext& rowset_writer_context) | ||
| } | ||
| _rowset_meta->set_tablet_uid(_context.tablet_uid); | ||
| _rowset_meta->set_tablet_schema(_context.tablet_schema); | ||
| _context.schema_change_recorder = | ||
| std::make_shared<vectorized::schema_util::LocalSchemaChangeRecorder>(); | ||
| _context.segment_collector = std::make_shared<SegmentCollectorT<BetaRowsetWriter>>(this); | ||
| _context.file_writer_creator = std::make_shared<FileWriterCreatorT<BetaRowsetWriter>>(this); | ||
| RETURN_IF_ERROR(_segment_creator.init(_context)); | ||
| @@ -446,6 +444,10 @@ Status BetaRowsetWriter::flush_memtable(vectorized::Block* block, int32_t segmen | ||
| } | ||
| TabletSchemaSPtr flush_schema; | ||
| if (_context.tablet_schema->num_variant_columns() > 0) { | ||
| // Unfold variant column | ||
| RETURN_IF_ERROR(expand_variant_to_subcolumns(*block, flush_schema)); | ||
| } | ||
| { | ||
| SCOPED_RAW_TIMER(&_segment_writer_ns); | ||
| RETURN_IF_ERROR( | ||
| @@ -522,6 +524,11 @@ Status BetaRowsetWriter::build(RowsetSharedPtr& rowset) { | ||
| _rowset_meta->set_newest_write_timestamp(UnixSeconds()); | ||
| } | ||
| // update rowset meta tablet schema if tablet schema updated | ||
| if (_context.tablet_schema->num_variant_columns() > 0) { | ||
| _rowset_meta->set_tablet_schema(_context.tablet_schema); | ||
| } | ||
| RETURN_NOT_OK_STATUS_WITH_WARN( | ||
| RowsetFactory::create_rowset(_context.tablet_schema, _context.rowset_dir, _rowset_meta, | ||
| &rowset), | ||
| @@ -544,6 +551,24 @@ bool BetaRowsetWriter::_is_segment_overlapping( | ||
| return false; | ||
| } | ||
| // update tablet schema when meet variant columns, before commit_txn | ||
| // Eg. rowset schema: A(int), B(float), C(int), D(int) | ||
| // _tabelt->tablet_schema: A(bigint), B(double) | ||
| // => update_schema: A(bigint), B(double), C(int), D(int) | ||
| void BetaRowsetWriter::update_rowset_schema(TabletSchemaSPtr flush_schema) { | ||
Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: method 'update_rowset_schema' can be made static [readability-convert-member-functions-to-static] be/src/olap/rowset/beta_rowset_writer.h:174: - void update_rowset_schema(TabletSchemaSPtr flush_schema);+ static void update_rowset_schema(TabletSchemaSPtr flush_schema);Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: method 'update_rowset_schema' can be made static [readability-convert-member-functions-to-static] be/src/olap/rowset/beta_rowset_writer.h:173: - void update_rowset_schema(TabletSchemaSPtr flush_schema);+ static void update_rowset_schema(TabletSchemaSPtr flush_schema); | ||
| std::lock_guard<std::mutex> lock(*(_context.schema_lock)); | ||
| TabletSchemaSPtr update_schema = std::make_shared<TabletSchema>(); | ||
| vectorized::schema_util::get_least_common_schema({_context.tablet_schema, flush_schema}, | ||
| update_schema); | ||
| CHECK_GE(update_schema->num_columns(), flush_schema->num_columns()) | ||
| << "Rowset merge schema columns count is " << update_schema->num_columns() | ||
| << ", but flush_schema is larger " << flush_schema->num_columns() | ||
| << " update_schema: " << update_schema->dump_structure() | ||
| << " flush_schema: " << flush_schema->dump_structure(); | ||
| _context.tablet_schema.swap(update_schema); | ||
| VLOG_DEBUG << "dump rs schema: " << _context.tablet_schema->dump_structure(); | ||
| } | ||
| void BetaRowsetWriter::_build_rowset_meta_with_spec_field( | ||
| RowsetMetaSharedPtr rowset_meta, const RowsetMetaSharedPtr& spec_rowset_meta) { | ||
| rowset_meta->set_num_rows(spec_rowset_meta->num_rows()); | ||
| @@ -751,4 +776,113 @@ Status BetaRowsetWriter::flush_segment_writer_for_segcompaction( | ||
| return Status::OK(); | ||
| } | ||
| Status BetaRowsetWriter::expand_variant_to_subcolumns(vectorized::Block& block, | ||
| TabletSchemaSPtr& flush_schema) { | ||
| size_t num_rows = block.rows(); | ||
| if (num_rows == 0) { | ||
| return Status::OK(); | ||
| } | ||
| std::vector<int> variant_column_pos; | ||
| if (is_partial_update()) { | ||
| // check columns that used to do partial updates should not include variant | ||
| for (int i : get_partial_update_info()->update_cids) { | ||
| if (_context.tablet_schema->columns()[i].is_variant_type()) { | ||
| return Status::InvalidArgument("Not implement partial updates for variant"); | ||
| } | ||
| } | ||
| } else { | ||
| for (int i = 0; i < _context.tablet_schema->columns().size(); ++i) { | ||
| if (_context.tablet_schema->columns()[i].is_variant_type()) { | ||
| variant_column_pos.push_back(i); | ||
| } | ||
| } | ||
| } | ||
| if (variant_column_pos.empty()) { | ||
| return Status::OK(); | ||
| } | ||
| try { | ||
| // Parse each variant column from raw string column | ||
| vectorized::schema_util::parse_variant_columns(block, variant_column_pos); | ||
| vectorized::schema_util::finalize_variant_columns(block, variant_column_pos, | ||
| false /*not ingore sparse*/); | ||
| vectorized::schema_util::encode_variant_sparse_subcolumns(block, variant_column_pos); | ||
| } catch (const doris::Exception& e) { | ||
| // TODO more graceful, max_filter_ratio | ||
| LOG(WARNING) << "encounter execption " << e.to_string(); | ||
| return Status::InternalError(e.to_string()); | ||
| } | ||
| // Dynamic Block consists of two parts, dynamic part of columns and static part of columns | ||
| // static extracted | ||
| // | --------- | ----------- | | ||
| // The static ones are original _tablet_schame columns | ||
| flush_schema = std::make_shared<TabletSchema>(); | ||
| flush_schema->copy_from(*_context.tablet_schema); | ||
| vectorized::Block flush_block(std::move(block)); | ||
| // If column already exist in original tablet schema, then we pick common type | ||
eldenmoon marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| // and cast column to common type, and modify tablet column to common type, | ||
| // otherwise it's a new column, we should add to frontend | ||
| auto append_column = [&](const TabletColumn& parent_variant, auto& column_entry_from_object) { | ||
| const std::string& column_name = | ||
| parent_variant.name_lower_case() + "." + column_entry_from_object->path.get_path(); | ||
| const vectorized::DataTypePtr& final_data_type_from_object = | ||
| column_entry_from_object->data.get_least_common_type(); | ||
| TabletColumn tablet_column; | ||
| vectorized::PathInDataBuilder full_path_builder; | ||
| auto full_path = full_path_builder.append(parent_variant.name_lower_case(), false) | ||
| .append(column_entry_from_object->path.get_parts(), false) | ||
| .build(); | ||
| vectorized::schema_util::get_column_by_type( | ||
| final_data_type_from_object, column_name, tablet_column, | ||
| vectorized::schema_util::ExtraInfo {.unique_id = -1, | ||
| .parent_unique_id = parent_variant.unique_id(), | ||
| .path_info = full_path}); | ||
| flush_schema->append_column(std::move(tablet_column)); | ||
| flush_block.insert({column_entry_from_object->data.get_finalized_column_ptr()->get_ptr(), | ||
| final_data_type_from_object, column_name}); | ||
| }; | ||
| // 1. Flatten variant column into flat columns, append flatten columns to the back of original Block and TabletSchema | ||
| // those columns are extracted columns, leave none extracted columns remain in original variant column, which is | ||
| // JSONB format at present. | ||
| // 2. Collect columns that need to be added or modified when data type changes or new columns encountered | ||
| for (size_t i = 0; i < variant_column_pos.size(); ++i) { | ||
| size_t variant_pos = variant_column_pos[i]; | ||
| vectorized::ColumnObject& object_column = assert_cast<vectorized::ColumnObject&>( | ||
| flush_block.get_by_position(variant_pos).column->assume_mutable_ref()); | ||
| const TabletColumn& parent_column = _context.tablet_schema->columns()[variant_pos]; | ||
| CHECK(object_column.is_finalized()); | ||
eldenmoon marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| std::shared_ptr<vectorized::ColumnObject::Subcolumns::Node> root; | ||
| for (auto& entry : object_column.get_subcolumns()) { | ||
| if (entry->path.empty()) { | ||
| // root | ||
| root = entry; | ||
| continue; | ||
| } | ||
| append_column(parent_column, entry); | ||
| } | ||
| // Create new variant column and set root column | ||
| auto obj = vectorized::ColumnObject::create(true, false); | ||
| // '{}' indicates a root path | ||
| static_cast<vectorized::ColumnObject*>(obj.get())->add_sub_column( | ||
| {}, root->data.get_finalized_column_ptr()->assume_mutable(), | ||
| root->data.get_least_common_type()); | ||
| flush_block.get_by_position(variant_pos).column = obj->get_ptr(); | ||
| vectorized::PathInDataBuilder full_root_path_builder; | ||
| auto full_root_path = | ||
| full_root_path_builder.append(parent_column.name_lower_case(), false).build(); | ||
| flush_schema->mutable_columns()[variant_pos].set_path_info(full_root_path); | ||
| VLOG_DEBUG << "set root_path : " << full_root_path.get_path(); | ||
| } | ||
| update_rowset_schema(flush_schema); | ||
| block.swap(flush_block); | ||
| VLOG_DEBUG << "dump block: " << block.dump_data(); | ||
| VLOG_DEBUG << "dump flush schema: " << flush_schema->dump_structure(); | ||
| return Status::OK(); | ||
| } | ||
| } // namespace doris | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -104,6 +104,8 @@ class BetaRowsetWriterV2 : public RowsetWriter { | ||
| PUniqueId load_id() override { return _context.load_id; } | ||
| const RowsetWriterContext& context() const override { return _context; } | ||
eldenmoon marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| Version version() override { return _context.version; } | ||
| int64_t num_rows() const override { return _segment_creator.num_rows_written(); } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -156,6 +156,7 @@ class RowsetWriter { | ||
| virtual std::shared_ptr<PartialUpdateInfo> get_partial_update_info() = 0; | ||
| virtual bool is_partial_update() = 0; | ||
| virtual const RowsetWriterContext& context() const = 0; | ||
eldenmoon marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| private: | ||
| DISALLOW_COPY_AND_ASSIGN(RowsetWriter); | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: method 'merge_objects' can be made static [readability-convert-member-functions-to-static]