Fix Variant Parquet scans on Spark 4.1+ - #15967
Conversation
Signed-off-by: Niranjan Artal <nartal@nvidia.com>
|
Signed-off-by: Niranjan Artal <nartal@nvidia.com>
|
build |
| s"${RapidsConf.ENABLE_PARQUET_READ} to true") | ||
| } | ||
|
|
||
| val schemaHasPushedVariant = readSchema.exists { field => |
There was a problem hiding this comment.
Spark only creates a VariantMetadata struct when PushVariantIntoScan can rewrite the access. It deliberately leaves a raw nested VariantType when the enclosing struct is selected. With a default-shredded Spark 4.1.1 file, SELECT s therefore reaches this block as struct<s:struct<v:variant>>, remains a GPU scan, and fails at runtime because the Parquet group also contains typed_value; I reproduced this against this head. Could we also fall back raw Variant schemas whenever shredded files may be read, unless the footer proves the layout is unshredded?
Suggested coverage:
- Write
named_struct('payload', parse_json(...)) AS nestedwith shredding enabled, select the entirenestedstruct, and assert bothFileSourceScanExecCPU fallback and CPU/GPU result parity. Please parameterize this for V1 and V2. - Write a shredded top-level Variant, read it with
spark.sql.variant.pushVariantIntoScan=false, and assert the same fallback and result parity.
Signed-off-by: Niranjan Artal <nartal@nvidia.com>
| if (schemaHasPotentiallyShreddedVariant) { | ||
| val reason = "GPU Parquet reader cannot safely read Variant columns when Spark allows " + | ||
| "shredded Variant input" | ||
| // A CPU-to-GPU transition cannot carry a raw Variant column, so keep the scan and its | ||
| // ancestor operators on CPU. | ||
| tagScanAndAncestorsForCpu(meta, reason) |
There was a problem hiding this comment.
Performance impact lacks validation
When shredded Variant input is allowed, this runtime change can move the Parquet scan and all its ancestor operators from GPU to CPU. The PR marks performance testing as unnecessary because the extraction implementation is unchanged, but that does not establish that the expanded CPU fallback cannot affect runtime performance. This violates the repository directive requiring performance validation or a verifiable exemption for runtime changes.
Rule Used: Report Performance: Not required as a high-severity finding unless the pull request is documentation-only or test-only, or its description gives a verifiable reason the change cannot affect runtime performance. A bug-fix label, small diff, or rarel... (source)
Knowledge Base Used: File format and file I/O support
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
There was a problem hiding this comment.
Updated the PR description.
|
build |
| plan.getTagValue(RapidsMeta.gpuSupportedTag).getOrElse(Set.empty) + reason) | ||
| case _ => | ||
| } | ||
| ancestor = ancestor.get.parent |
There was a problem hiding this comment.
This keeps walking even after the raw Variant has been consumed. I tried sum(try_variant_get(v, ...)) on a shredded file with scan pushdown disabled, and the entire Project -> partial HashAggregate -> Exchange -> final HashAggregate stayed on CPU. The Project already outputs only int, so a row-to-columnar transition above it should be safe. Could we stop after tagging the first ancestor whose output no longer contains VariantType? It would also be good to add an aggregate-above-extraction test that asserts only the scan/extraction prefix stays on CPU while the downstream aggregate returns to GPU.
Signed-off-by: Niranjan Artal <nartal@nvidia.com>
|
build |
Fixes #15952.
Description
Spark 4.1.1+ enables Variant shredding and pushes Variant extraction into Parquet scans by default. The pushed read schema contains synthetic Variant structs understood by Spark's CPU Parquet reader but not by the GPU Parquet reader. These scans could therefore fail with missing schema-index or empty-footer errors.
This PR detects pushed Variant structs using Spark's
VariantMetadataand prevents the Parquet scan from running on GPU, allowing it to fall back cleanly to CPU. Spark 4.0 behavior is unchanged.The integration tests now cover:
try_variant_getexecutes usingGpuVariantGetfor Parquet V1 and V2.Validation:
variant_test.py: 36 passed.Performance:
This correctness fix intentionally falls back to CPU when a raw Variant column may use Spark's shredded Parquet representation. The affected shredded path failed before this change, so it has no successful GPU baseline to compare against. GPU execution for explicitly unshredded Variant input remains unchanged.
GPU support for Variant Parquet scans is tracked by #15180. Pushed Variant extraction support is tracked separately by #14251.
Checklists
Documentation
Testing
Performance