morningman opened a new pull request, #69581:
URL: https://github.com/apache/doris/pull/69581

   ### What problem does this PR solve?
   
   Issue Number: None
   
   Related PR: #65730 #66608 #66805 #66841 #66999 #67005 #67011 #67110 #67268 
#67289 #67325 #67650 #67921 #68028 #68335 #68375 #68615 #68690
   
   Problem Summary:
   
   **In short.** This ports the Lance BE read path of branch-4.1 / branch-4.2 
to master, in its branch-4.2 form as of `cabcf45c1af`; it gathers the BE parts 
of the PRs listed above. Master links `liblance_c` but has no Lance reader, so 
every `FORMAT_LANCE` scan fails today. With this PR the BE reads Lance datasets 
through FileScannerV2: plain scans, vector search and full-text search, 
predicate and runtime-filter pushdown, the schema fetch of a local Lance TVF, 
and the second phase of TopN lazy materialization. The PR is BE only. The FE 
connector plugin and the regression suites come in separate PRs, so until then 
nothing on master plans a Lance scan, and the BE unit tests carry the proof.
   
   Original authors: @zhangstar333 @Gabriel39 @wangzhaobo957-cloud @Jay-ju 
@FANNG1
   
   **Background.** Lance shipped in 4.1.4: the Lance catalog, `local()` / 
`s3()` with `format=lance`, and the `vector_search` / `full_text_search` TVFs. 
On master the FE side is being rebuilt as a connector plugin 
(`fe-connector-lance`), and the BE needs the reader from 4.x. The thrift ids 
are the branch-4.1 / 4.2 ones, so a BE built from master also reads the Lance 
scan ranges that a 4.x FE sends during a rolling upgrade.
   
   **The problem, and what it cost.**
   
   | | master today | with this PR |
   |---|---|---|
   | A `FORMAT_LANCE` scan | `file_scan_operator` keeps it off FileScannerV2 
and V1 has no Lance path, so the query fails | read by `LanceTableReader` in 
FileScannerV2 |
   | `fetch_table_schema` for a local Lance TVF | not handled | returns the 
Arrow schema mapped to Doris types; Null leaves keep `NULL_TYPE` |
   | The row location of a Lance row in TopN lazy materialization | 
`GlobalRowLoacationV2` only has a 32-bit row id, but a Lance row id is a 64-bit 
id within the snapshot | a version 1 layout carries the 64-bit row id; phase 
two reads the rows with the dataset's `take_rows` |
   
   **How this PR fixes it.**
   
   - Reader: `be/src/format_v2/lance/*` and 
`be/src/format_v2/table/lance_reader.*`, as on branch-4.2 except one local 
renamed for master's `-Wshadow`. The unit tests construct 
`RuntimeState(TQueryOptions(), globals)`, because master removed the 
globals-only constructor.
   - FileScannerV2: `is_supported`, the reader dispatch and `_to_file_format` 
handle `FORMAT_LANCE` / `"lance"`; `FileFormat::LANCE` is added to its two 
exhaustive switches. Lance queries use FileScannerV2 whatever 
`enable_file_scanner_v2` says, as ADBC and fluss do: there is no V1 Lance 
reader, and the variable is fuzzy in the regression harness. On branch-4.2 a 
Lance query fails with NotSupported when the variable is off. Loads are 
unchanged.
   - Row locations: `ROW_VERSION {FILE_LOCAL_ROW_ID = 0, LANCE_DATASET_ROW_ID = 
1}` and a union layout for `GlobalRowLoacationV2`. Version 0 keeps its byte 
layout, which static asserts pin. `PRequestBlockDesc.row_id` becomes `uint64` 
(a proto2 varint, so the wire format is compatible). The materialization 
operator decodes row locations by version, rejects an unknown version or a 
wrong size, and stamps `row_location_version`. `RowIdStorageReader` validates 
the counts and the version, range-checks internal row ids against `uint32`, and 
groups Lance rows by plan node, snapshot version and dataset URI, so each 
dataset is read with one `take_rows`. Master's segment batching, scan-slot 
dedup and fetch concurrency stay as they are.
   - Thrift (`PlanNodes.thrift`): the external search request body 
(`TVectorElementType`, `TVectorMetric`, `TSearchVector`, `TVectorSearchParams`, 
`TFtsCoverageMode`, `TFtsQueryType`, `TFtsMatchOperator`, 
`TFullTextSearchParams`, `TSearchFilterFormat`, `TSearchFilter`, 
`TVectorSearchOptions`, `TExternalSearchQuery`), `TExternalSearchRequest` 2-4 
and `TLanceFileDesc` 4-6, all with the branch-4.1 / 4.2 ids. The enums spell 
out their 4.x values. No id is reused.
   - Core: `to_protobuf` keeps `NULL_TYPE` for a NULL literal type, so a Null 
leaf in ARRAY / MAP / STRUCT no longer comes back as BOOLEAN. The nullable 
serde reads an Arrow Null array as NULLs without touching buffers that the 
array does not have.
   - Configs, caches and metrics, with the 4.x names and defaults:
   
     | Config | Default |
     |---|---|
     | `lance_index_cache_size_bytes` | 10 GiB |
     | `lance_metadata_cache_size_bytes` | 1 GiB |
     | `enable_lance_data_cache` | true |
     | `lance_data_cache_path` | `${DORIS_HOME}/lance_data_cache` |
     | `lance_data_cache_disk_capacity_bytes` | 100 GiB |
     | `lance_data_cache_read_block_size_bytes` | 1 MiB |
     | `lance_io_buffer_size_bytes` (mutable) | 2 GiB |
     | `lance_batch_readahead` (mutable) | 5 |
     | `lance_fragment_readahead` (mutable) | 5 |
   
     The BE-wide Lance session (index cache, metadata cache and the optional 
Foyer disk cache) is created by the first Lance scan, so a BE that never reads 
Lance creates no cache directory. The first six configs take effect after a 
restart. Ten `lance_session_*` metrics report the two in-memory caches. With 
the defaults, the disk tier keeps 51,200 sparse 2 MiB block files open from the 
first Lance scan on (100 GiB in blocks of twice the read block size), the same 
as on branch-4.1 / 4.2. Size `lance_data_cache_disk_capacity_bytes` and 
`lance_data_cache_read_block_size_bytes` against the BE's open-file limit, or 
set `enable_lance_data_cache = false`.
   - Build: macOS links `-framework IOKit`. This is the first time objects of 
`liblance_c.a` are pulled into `doris_be`, so the binary and the link time grow.
   
   Not included: the `MaterializationOperator::push` timer fix (#69579); the 
Lance index metadata scanner (`LANCE_INDEX_ENTRIES`); the FE side, including 
the rolling-upgrade guard that keeps Lance lazy materialization off while an 
old BE could decode a version 1 row location as version 0; the regression 
suites; and the 4.x changes after `cabcf45c1af` (#68707, #68813, #68815). The 
`InitReaderAvgTime` / `GetBlockAvgTime` profile fix that #67005 carried goes in 
a separate PR.
   
   **Results.**
   
   | | master | with this PR |
   |---|---|---|
   | A `FORMAT_LANCE` query | fails before reading anything | read by 
`LanceTableReader` in FileScannerV2 |
   | A Lance row in the second phase of TopN lazy materialization | cannot be 
represented | a version 1 row location, read back with `take_rows` |
   | A row location of an unknown version or size in phase two | decoded as 
version 0 | rejected with an error |
   
   BE unit tests (ASAN): 238 cases. They cover the Lance suites (78: 
`LanceTableReader*` 57, `LanceNestedNullTest` 10, 
`LanceRuntimeFilterHelperTest` 8, `LanceSessionManagerTest` 3); the 
row-location protocol (`MaterializationSharedStateTest`, 
`RowIdStorageReaderTest`, and the new `RowIdFetchRequestValidationTest`: count 
mismatch, unknown version, a Lance version on an internal mapping, an internal 
row id of 2^32); `FileScannerV2Test` with the new 
`LanceQueriesAlwaysUseScannerV2`, `FileScanOperatorAdbcTest` and 
`FileScanOperatorFlussTest`; the ORC / Parquet global row id tests that now 
read `.file_local`; and the Arrow / protobuf serde suites. 237 pass locally. 
`LanceTableReaderVectorSearchTest.MultiVectorScoresFiltersOffsetsAndIndexedCoverage`
 checks ANN timing metrics that the lance-c revision pinned by master reports; 
the local third-party build predates that revision, so this case is left to CI.
   
   ### Release note
   
   Add nine `lance_*` BE configs and `lance_session_*` BE metrics. They take 
effect once the FE can plan Lance scans.
   
   ### Check List (For Author)
   
   - Test <!-- At least one of them must be included. -->
       - [ ] Regression test
       - [x] Unit Test
           - `run-be-ut.sh --run --filter=...` with the suites listed under 
Results: 237 of 238 pass on macOS arm64 (ASAN). The remaining case needs the 
lance-c revision that master pins (see Results).
           - `build-support/check-build-hygiene.sh`, clang-format 16 and 
`build-support/run-clang-tidy.sh` on the changed files: all pass; clang-tidy 
reports nothing on the changed lines of the 38 changed C++ files.
       - [ ] Manual test (add detailed scripts or steps below)
       - [ ] No need to test or manual test. Explain why:
   - Behavior changed:
       - [ ] No.
       - [x] Yes. `PRequestBlockDesc.row_id` is `uint64`; phase two of TopN 
lazy materialization rejects row locations of an unknown version or size; 
`FORMAT_LANCE` scans run on FileScannerV2.
   - Does this need documentation?
       - [x] No. Lance is documented with the FE connector.
       - [ ] Yes. <!-- Add document PR link here. eg: 
https://github.com/apache/doris-website/pull/1214 -->
   
   ### Check List (For Reviewer who merge this PR)
   
   - [ ] Confirm the release note
   - [ ] Confirm test cases
   - [ ] Confirm document
   - [ ] Add branch pick label <!-- Add branch pick label that this PR should 
merge into -->
   


-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to