Biobank-scale bind performance
Region-filtered read_pfile random-access queries now bind in ~milliseconds instead of ~seconds at biobank scale. Measured end-to-end on synthetic 7M samples × 1.5M variants with parquet companion files:
| Phase | Before | After |
|---|---|---|
| pvar load | 1355 ms | 3 ms |
| psam load | 6658 ms | 0 ms |
| effective-variant-list | 28 ms | 0 ms |
| Total bind | 8041 ms | ~7 ms |
Projects to sub-100ms bind at the 170M-variant imputation panel scale. No SQL API changes.
What changed
- Columnar
VariantMetadataIndex— the internal pvar representation is now typed vectors (chroms,positions,ids,refs,alts) instead of a synthesized#CHROM\tPOS\t…text buffer that had to be re-parsed. Adds achrom_offsetsindex for O(log N) region lookup and a sparsevidx_map+local_to_vidxmode for pushdown. - Parquet region pushdown — when
region :=is set and the pvar is parquet, the bind issuesSELECT … WHERE "#CHROM" = $1 AND POS BETWEEN $2 AND $3withfile_row_numberso only matching rows are materialized. Uses row-group statistics pruning + column projection. - Smart psam load — when the query doesn't need IID strings (no VARCHAR sample filter, no
genotypes := 'columns'/'struct', notorient := 'genotype'/'sample'), the loader returns a sample count via parquet footer metadata in O(num_row_groups) and skips the ~600ms of string copies. - Lazy
iid_to_idx— built only on first VARCHAR sample lookup, with duplicate-IID detection moved to the lazy-build path. - Binary-search region/CPRA lookup —
ParseRegion,ResolveByCpra, and theread_pfileeffective-variant-list loop all usechrom_offsets+std::lower_boundinstead of linear scans. - Env-gated bind timing probes —
PLINKING_BIND_PROFILE=1emits phase timings to stderr. Zero overhead when off.
Correctness hardening
- Text
.pvar/.bimparser rejects truncated/malformed lines with a clearInvalidInputException(file + byte offset + missing fields) instead of silently pushing default-initialized columns. BuildChromOffsetsdetects and throws on non-contiguous chromosome runs in generic SQL-view sources (previously silently dropped). PLINK-format files are unaffected.SampleInfo::EnsureIidMapthrows with an actionable message when called against a count-only sample load (indicates an internal bug), instead of a confusing downstream "sample not found".- Region-pushdown SQL uses a prepared statement for user-controlled values; the chrom column (
#CHROMvsCHROM) is detected via upfront schema introspection instead of error-driven retry.
Other readers
plink_ld's pairwise lookup now goes through a shared public BuildVariantIdIndex, which is also sparse-safe. plink_score's region-restricted ID map uses columnar access.