Elyra
Elyra The coding agent e The native code editor Elyra Grove Native local development environment Askr The real server for Laravel & PHP Elyra Framework Rust + Svelte 5 framework for desktop apps Elyra Conductor Local project conductor Elyra SQL Server MySQL-compatible SQL server in Rust Elyra SQL Client Native desktop SQL workbench Elyra SQL Anywhere Replication-ready SQL engine Elyra DataGrid Server-driven data grid for Laravel
Elyra

Performance

Elyra DataGrid is built to stay fast at scale by pushing work to the database and keeping both the DOM and the query cost bounded.

For measured numbers on a 10M-row table (and how to reproduce them), see Benchmarks.

Principles

  1. O(viewport), never O(data). Only the visible window of rows is fetched and rendered. Row virtualization (Svelte/Vue) and column virtualization keep the DOM small regardless of dataset or column count.
  2. Opt-in cost. Nothing expensive runs unless a feature needs it:
    • total (row count) and footer aggregates are requested only when paging / aggregates are enabled, and are cached per filter — paging or sorting does not recompute them.
    • Facets are lazy — computed only when a filter dropdown opens, and cached until the filter changes.
  3. Push down to SQL. Sorting, filtering, grouping, aggregation and search execute in ElyraSQL, not in JavaScript.
  4. Stream exports. Exports read from a server cursor, so memory is constant even for millions of rows.
  5. Server-seeded first paint. initialData renders the first page instantly without waiting for a client round-trip.

Measured behavior (10M-row table, ElyraSQL)

Interaction Cost
First render (per filter) ~total + aggregates (one-time)
Paging / sorting (same filter) ~viewport query only (totals cached)
Opening a filter dropdown one lazy FACET() (cached after)
Export streamed, constant memory

In practice, once a filter is set, paging is dominated by the viewport query and the cached totals are reused — subsequent pages are effectively instant.

Indexing guidance (ElyraSQL)

  • Index columns used in selective WHERE filters — filtered COUNT/aggregates become index reads instead of full scans.
  • Prefer grouping/faceting on lower-cardinality columns (memory is proportional to the number of groups, not rows).
  • Keep meta: ['total'] opt-in on very large unfiltered sets if you do not need an exact count.

Known engine consideration

Sorting at scale depends on ElyraSQL's index-backed top-N. Measured on a 10M-row table (ElyraSQL 1.4.5):

Query shape Cost
ORDER BY id [DESC] LIMIT n (primary key) ~50 ms
ORDER BY <indexed_col> DESC LIMIT n ~50 ms (index-backed top-N)
ORDER BY <indexed_col> ASC LIMIT n ~5 s (full sort)
ORDER BY <col> <dir>, id ASC LIMIT n (compound) ~5 s (full sort)
... LIMIT n OFFSET m (deep page) grows with m

The grid appends a stable key tiebreaker in the same direction as the sort (ORDER BY col ASC, id ASC / col DESC, id DESC). This is deterministic (equal-value rows page consistently) and index-friendly: a compound (col, id) index can, in principle, satisfy the whole top-N as a forward index scan.

Engine status (ElyraSQL 1.4.7): index-backed top-N now works in both directions, including the compound (col, key) order the grid emits. Measured on 10M rows with a compound (revenue, id) index:

Query Cost
ORDER BY revenue DESC LIMIT 40 ~55 ms
ORDER BY revenue ASC LIMIT 40 ~53 ms
ORDER BY revenue DESC, id DESC LIMIT 40 ~53 ms
ORDER BY revenue ASC, id ASC LIMIT 40 ~53 ms
grid sort via API (whole chain) ~32–43 ms

Sorting a 10M-row table by a secondary column is now ~40 ms end-to-end (it was ~6 s). Add a compound (sortColumn, keyColumn) index on columns you sort at scale so the engine can serve the grid's col <dir>, key <dir> order as an index top-N.

Note: key > ? keyset seeks are still full scans on ElyraSQL, so the export streams via a single unbuffered pass (see Export) rather than keyset pagination.

Paging, filtering, grouping and export remain cheap regardless of sort.

Client-side tips

  • Give columns a width when using column virtualization for accurate offsets.
  • Match paging.rowHeight to your real row height for correct virtual scrolling.
  • Use persistKey to avoid re-deriving layout on every visit.