Skip to content

feat: skip per-dim discovery scans when query is an unfiltered scan#193

Merged
alxmrs merged 1 commit into
xqlsystems:mainfrom
ghostiee-11:feat/template-coord-fastpath
Jun 29, 2026
Merged

feat: skip per-dim discovery scans when query is an unfiltered scan#193
alxmrs merged 1 commit into
xqlsystems:mainfrom
ghostiee-11:feat/template-coord-fastpath

Conversation

@ghostiee-11

Copy link
Copy Markdown
Contributor

For an unfiltered scan over a single registered table (Projection / Sort / TableScan / SubqueryAlias only) the result's coord extent is exactly the source's. _build_lazy_scan now reuses the registered Dataset's coord arrays directly instead of running one DISTINCT scan per dim. Filtered / aggregated / joined / limited / multi-table queries fall back to the existing discovery path unchanged. Also closes #171 (lazy round-trip now preserves source dim order, e.g. descending lat).

Results

to_dataset() construction on NCEP air_temperature (chunks={'time':24}):

stage before after
peak memory 77 MB 0.1 MB
wall time 3.4 s 7 ms

171 / 171 tests pass; detector audited across 8 query shapes.

When a query is a pure unfiltered scan over a single registered
template (Projection / Sort / TableScan / SubqueryAlias only), the
result's coordinate extent is exactly the registered Dataset's.
Reuse its coord arrays directly instead of running one DISTINCT scan
per dim. Filtered, aggregated, joined, limited, multi-table queries
fall back to the existing per-dim discovery path unchanged.

The detector walks the logical plan and returns the scanned table
name; coord values are then sourced from that registered Dataset, not
from any user-supplied template= argument (which is only for metadata
recovery). That keeps the fast path correct when a user with multiple
registered Datasets passes a metadata template that differs from the
query's actual source.

Construction cost on NCEP air_temperature (chunks={'time':24}):
- before: peak 77 MB, wall 3.4 s (3x full-source scans for 3 dims)
- after : peak 0.1 MB, wall 7 ms

Also fixes xarray-sql#171 (stable dim order on the lazy round-trip):
the discovery path's .distinct().sort() forced ascending; the
template-coord fast path returns coords in source order, so a source
with descending lat (e.g. air_temperature: 75 -> 15) round-trips
descending instead of being flipped.

@alxmrs alxmrs left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few notes -- great idea. I can't wait to benchmark this optimization.

Comment thread tests/test_ds.py
ctx.register_table("air", table)
ctx._registered_datasets["air"] = air_dataset_small

reads.clear()

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does the clear do?

Comment thread tests/test_ds.py
table = read_xarray_table(
air_dataset_small,
chunks={"time": 6},
_iteration_callback=lambda block, proj: reads.append(block),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make this append consistent with the above version (block or proj)

Comment thread tests/test_ds.py
Comment on lines +282 to +284
out = ctx.sql('SELECT * FROM "air"').to_dataset(
dims=["time", "lat", "lon"], template=other
)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, good test

Comment thread tests/test_ds.py
)


def test_round_trip_preserves_descending_lat_on_lazy_path(air_dataset_small):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice

Comment thread xarray_sql/ds.py
_PURE_SCAN_NODES = {"Projection", "Sort", "TableScan", "SubqueryAlias"}


def _unfiltered_scan_table(inner_df: Any) -> str | None:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice

@alxmrs
alxmrs merged commit a5faf1a into xqlsystems:main Jun 29, 2026
12 checks passed
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.

to_dataset should preserve source dim order without test-side sortby

2 participants