Skip to content

[Draft] Batch updated by key groups#303

Open
suddendust wants to merge 2 commits into
mainfrom
feat/292
Open

[Draft] Batch updated by key groups#303
suddendust wants to merge 2 commits into
mainfrom
feat/292

Conversation

@suddendust
Copy link
Copy Markdown
Contributor

@suddendust suddendust commented Apr 30, 2026

Batch updates by key groups for bulkUpdate

Problem

The previous bulkUpdate implementation in FlatPostgresCollection executed a separate SQL UPDATE per key, even when multiple keys shared identical update operations (same columns, operators, and paths). For bulk updates with N keys, this meant N individual database round-trips — each preparing and executing its own PreparedStatement.

Key 1: UPDATE t SET price=?, tags=... WHERE pk = ?   -- round-trip 1
Key 5: UPDATE t SET price=?, tags=... WHERE pk = ?   -- round-trip 2  (same SQL shape!)
Key 8: UPDATE t SET price=?, tags=... WHERE pk = ?   -- round-trip 3  (same SQL shape!)

This is inefficient when many keys receive the same type of update, which is a common pattern in practice.

Solution

Keys are now grouped by their "update shape" — a canonical key derived from the sorted combination of column:operator:path — and each group is executed as a single JDBC batch using PreparedStatement.addBatch() / executeBatch().

New components

  • groupKeysByUpdateShape() — Iterates over all (Key, Collection<SubDocumentUpdate>) entries, validates and resolves columns, then buckets keys into groups that share the same shape key.

  • computeUpdateShapeKey() — Builds a deterministic string signature by sorting updates by path and concatenating column:operator:path; for each. Keys with identical signatures share a SQL template.

  • KeyUpdateGroup (inner class) — Holds the resolved columns, list of keys, and per-key update values for a single group.

  • executeBatchUpdate() — Builds one PreparedStatement from the group's SQL template, then loops over all keys in the group: binds per-key parameter values (including the lastUpdatedTs column), calls addBatch(), and finally executeBatch() in a single round-trip.

What changed in the existing flow

Before After
bulkUpdate → loop per key → updateSingleKey()executeKeyUpdate() bulkUpdategroupKeysByUpdateShape() → loop per group → executeBatchUpdate()
N keys = N round-trips N keys in G groups = G round-trips (G ≤ N)
Tracked updated keys via Set<Key> Tracks total updated count via int from executeBatch() results
updateSingleKey() method Removed — grouping + batch replaces it

Error handling is preserved: failures in one group are logged and skipped; other groups continue (no cross-group atomicity).

Files changed

  • FlatPostgresCollection.java (+189 / −41) — Core implementation: replaced per-key loop with grouping and JDBC batching. Added groupKeysByUpdateShape(), computeUpdateShapeKey(), executeBatchUpdate(), and KeyUpdateGroup inner class. Removed updateSingleKey().

  • FlatCollectionWriteTest.java (+118) — New integration test testBulkUpdateMultipleGroupsComplexOperations that exercises 3 distinct update groups across 7 keys:

    • Group 1 (keys 1, 5, 8): SET on primitive field + APPEND_TO_LIST on array
    • Group 2 (keys 3, 7): SET on nested JSONB fields
    • Group 3 (keys 2, 6): ADD on numeric field + REMOVE_ALL_FROM_LIST on array

Performance Improvements

TBD

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 30, 2026

Codecov Report

❌ Patch coverage is 85.85859% with 14 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.51%. Comparing base (059875b) to head (fb9132c).

Files with missing lines Patch % Lines
...documentstore/postgres/FlatPostgresCollection.java 85.85% 10 Missing and 4 partials ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main     #303      +/-   ##
============================================
- Coverage     81.68%   81.51%   -0.18%     
  Complexity     1532     1532              
============================================
  Files           241      241              
  Lines          7420     7503      +83     
  Branches        718      726       +8     
============================================
+ Hits           6061     6116      +55     
- Misses          912      938      +26     
- Partials        447      449       +2     
Flag Coverage Δ
integration 81.51% <85.85%> (-0.18%) ⬇️
unit 55.11% <0.00%> (-0.62%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 30, 2026

Test Results

  122 files  ±0    122 suites  ±0   35s ⏱️ -18s
  830 tests +1    829 ✅ +1  1 💤 ±0  0 ❌ ±0 
1 167 runs  +1  1 166 ✅ +1  1 💤 ±0  0 ❌ ±0 

Results for commit fb9132c. ± Comparison against base commit 059875b.

♻️ This comment has been updated with latest results.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant