Optimize relational tablet batch inserts#18132
Conversation
|
I found a few issues that should be addressed before merging:
In InsertTablets.validateTableSchema, the call to validateTableSchema passes allowCreateTable=false. This makes ITableSession.insertTablets(List) fail when inserting into a new table, while the existing single-tablet insert path can auto-create the table. The current integration tests all create the tables first, so this behavior difference is not covered. Please either align this with the single-tablet path or clearly document and test that batch tablet insertion requires the table to exist.
Session.insertRelationalTablets always sends the request through getDefaultSessionConnection().insertTablets(request) and ignores RedirectException. The existing insertRelationalTablet path uses the table-model leader cache and groups rows/tablets by endpoint when redirection is enabled. In a cluster, this new path can keep sending requests to the default node and will not refresh tableModelDeviceIdToEndpoint, which may offset the intended performance gain. Please consider reusing or extending the existing relational tablet redirection logic for the batch path.
recordMergeTabletsCost is called from finally, so failed RPCs or execution failures still contribute to the auto-disable decision. This can permanently disable merge due to failure-path latency rather than actual merge overhead. It would be safer to record the cost only after a successful insert, or explicitly exclude failed attempts from the heuristic. Question: Is insertTablets intentionally not supposed to support auto table creation? If yes, the API documentation and tests should make that clear. |
|
Thanks for addressing the previous review comments. I re-checked the latest revision and there is still one blocking issue. High: the new table-model The current batch path catches This is also visible in the current CI failure, and it hits the new/related tests directly:
Could you please make the batch |
| request.addToColumnCategoriesList(toEnumOrdinalsAsBytes(tablet.getColumnTypes())); | ||
| } | ||
| try { | ||
| getDefaultSessionConnection().insertTablets(request); |
There was a problem hiding this comment.
High: In the enableRedirection == false branch, this still calls the one-argument insertTablets(request) overload. That overload passes request.getPrefixPaths() to verifySuccessWithRedirectionForMultiDevices; for a relational request this list has one table name per Tablet, while the server now emits one redirect sub-status per row. For example, a single two-row Tablet whose rows are redirected produces two sub-statuses but only one prefix path, so processing the second status accesses devices.get(1) and throws IndexOutOfBoundsException after the write has already succeeded, instead of reaching the ignored RedirectException. Please pass row-aligned device IDs here as the enabled-redirection path does, or use a verification path that deliberately ignores redirect metadata. A regression test should cover redirection disabled, a multi-row Tablet, and a non-local leader.
| long mergeTabletsCost = 0; | ||
| if (enableMergeTablets) { | ||
| final long mergeTabletsStartTime = System.nanoTime(); | ||
| tablets = mergeRelationalTablets(tablets); |
There was a problem hiding this comment.
Low: Zero-row relational Tablets are not filtered before this merge. Two compatible empty Tablets are merged into a new Tablet with rowCount == 0, hence zero-capacity value arrays. With redirection enabled, addRelationalTabletToGroup then calls SessionUtils.isTabletContainsSingleDevice, which evaluates getDeviceID(0); a tagged zero-capacity Tablet throws IndexOutOfBoundsException there. This is inconsistent with insertRelationalTablet, which explicitly treats rowSize == 0 as a no-op, and with the server parser, which skips empty Tablets. Please filter zero-row Tablets before merging, define the all-empty batch behavior, and add a regression test.
Description
This PR optimizes relational insertTablets handling in the Java Session client.
Tests