Skip to content

Commit fdbdf6f

Browse files
committed
perf: skip flatMap copy for single-shard merge, cache distinct column keys
- merge.ts: single-shard results with no offset/limit now skip the flatMap copy entirely — avoids doubling peak memory in the QueryDO (128MB ceiling) for the common case of one fragment result. - operators.ts: DistinctOperator.nextColumnar caches the resolved column list (from batch.columns.keys()) across batches instead of re-allocating Array.from() on every batch for DISTINCT(*) queries.
1 parent 47dc97b commit fdbdf6f

File tree

2 files changed

+11
-5
lines changed

2 files changed

+11
-5
lines changed

src/merge.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -224,12 +224,17 @@ export function mergeQueryResults(
224224
// Fallback: mixed or row-based
225225
for (const p of partials) ensureRows(p);
226226
let rows: Row[];
227-
const allRows = partials.flatMap((p) => p.rows);
228227
const off = query.offset ?? 0;
229-
if (off > 0 || query.limit !== undefined) {
230-
rows = allRows.slice(off, query.limit !== undefined ? off + query.limit : undefined);
228+
if (partials.length === 1 && off === 0 && query.limit === undefined) {
229+
// Single shard, no slicing — avoid flatMap copy
230+
rows = partials[0].rows;
231231
} else {
232-
rows = allRows;
232+
const allRows = partials.flatMap((p) => p.rows);
233+
if (off > 0 || query.limit !== undefined) {
234+
rows = allRows.slice(off, query.limit !== undefined ? off + query.limit : undefined);
235+
} else {
236+
rows = allRows;
237+
}
233238
}
234239

235240
return { rows, rowCount: rows.length, columns, ...baseResult };

src/operators.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1077,6 +1077,7 @@ export class DistinctOperator implements Operator {
10771077
private upstream: Operator;
10781078
private columns: string[];
10791079
private seen = new Set<string>();
1080+
private _resolvedCols: string[] | null = null;
10801081

10811082
constructor(upstream: Operator, columns: string[]) {
10821083
this.upstream = upstream;
@@ -1100,7 +1101,7 @@ export class DistinctOperator implements Operator {
11001101

11011102
const indices = batch.selection ?? identityIndices(batch.rowCount);
11021103
const kept: number[] = [];
1103-
const cols = this.columns.length > 0 ? this.columns : Array.from(batch.columns.keys());
1104+
const cols = this.columns.length > 0 ? this.columns : (this._resolvedCols ??= Array.from(batch.columns.keys()));
11041105
// Pre-extract column arrays to avoid Map.get per column per row
11051106
const colArrays: ((number | bigint | string | boolean | null)[] | undefined)[] = new Array(cols.length);
11061107
for (let g = 0; g < cols.length; g++) colArrays[g] = batch.columns.get(cols[g]) ?? undefined;

0 commit comments

Comments
 (0)