SQL on FHIR WG Meetings




SQL on FHIR WG Meeting — February 18, 2025
Nikolai Ryzhikov
CTO at Health Samurai
Dan Gottlieb
Principal, Data standards Central Square Solutions
Arjun Sanyal
Principal Antidote Solutions
Bashir Sadjad
Software Engineer at Google
John Grimes
Principal Research Consultant CSIRO
Feb 18, 2025
Topics discussed:
- Dan generated 400,000 patients and 84 million observations and pointed DuckDB at them. Filtering inside the array expression before unnesting took two seconds; unnesting first and filtering afterwards took two minutes — same output either way, so a fully optimised planner shouldn't care. It clearly does, and Bashir's read is that Spark's query planner would have handled it.
- The odd part: the 75GB NDJSON file and the 100MB Parquet file both took around two minutes. Bashir said the I/O gap alone should have settled it, so something is going badly wrong on the Parquet side. Nikolai guessed DuckDB converts both into its own in-memory representation on the fly, and John pointed out that Parquet only pays off if the engine pushes predicates all the way down and grabs just the slices it needs — DuckDB may not have all those prerequisites built yet.
- The finding Dan actually cared about: if a ViewDefinition touches a field that isn't in the Parquet schema, DuckDB errors instead of returning null — even with forEachOrNull. Over NDJSON he avoids this by imposing a schema he builds from the ViewDefinition's FHIRPaths, but Parquet behaves like a table with a fixed schema and won't let you overlay one. The workaround is writing a fake file of nulls just to get the fields into the merged schema, which nobody wanted to defend.
- Dan framed why that matters beyond one engine: it forces you to introspect every file in your data lake before you can compile a ViewDefinition into SQL, coupling the query to whatever data it happens to be pointed at that day. John confirmed Spark lets you supply a schema on read, so the open question is which other engines can — and if none of them can, the minimal-schema idea gets a lot weaker.
- Bashir pulled apart two problems the group kept merging. When a ViewDefinition is compiled to SQL there's a runner in the middle that can inspect the schema, work out the needed fields and ask the engine to merge; when a data scientist writes raw SQL straight over the Parquet files, there's nothing in between and the engine has to cope alone. He thinks both are worth supporting. The group also settled some vocabulary — minimal (follows the data), focused (follows the query), comprehensive (follows the FHIR profile) — and agreed to test across three tiers of engine: Spark-like, DuckDB and ClickHouse, and the cloud warehouses.