Drop _tmp_metadata_row_index column from the output of Delta Scan on GPU - #13991
Conversation
There was a problem hiding this comment.
My understanding of this bug is that the _tmp_metadata_row_index is still part of the output of GpuFileSourceScanExec even after DeltaProvider.pruneFileMetadata(). This is messing up with the the logic to find the partition column. My suggestion is to modify DeltaProviderBase.pruneFileMetadata() as below, so that we can have the metadata pruning logic in one place. I think this should be safe as we never use the _tmp_metadata_row_index column anyway. I tested this change manually and it seems to work.
diff --git a/delta-lake/common/src/main/delta-33x-40x/scala/com/nvidia/spark/rapids/delta/common/DeltaProviderBase.scala b/delta-lake/common/src/main/delta-33x-40x/scala/com/nvidia/spark/rapids/delta/common/DeltaProviderBase.scala
index 126de3544..96ff4e0e1 100644
--- a/delta-lake/common/src/main/delta-33x-40x/scala/com/nvidia/spark/rapids/delta/common/DeltaProviderBase.scala
+++ b/delta-lake/common/src/main/delta-33x-40x/scala/com/nvidia/spark/rapids/delta/common/DeltaProviderBase.scala
@@ -162,6 +162,7 @@ abstract class DeltaProviderBase extends DeltaIOProvider {
dvFilterInput.copy(projectList = inputList.filterNot(_.name == "_metadata"))
.withNewChildren(Seq(
fsse.copy(
+ originalOutput = fsse.originalOutput.filterNot(_.name == "_tmp_metadata_row_index"),
requiredSchema = StructType(
fsse.requiredSchema.filterNot(_.name == "_tmp_metadata_row_index")
))(fsse.rapidsConf)))))))
Also, please add some test to cover this bug.
Thanks, I think that is a much cleaner approach. I will update |
425e311 to
0cf8bb5
Compare
Signed-off-by: Raza Jafri <raza.jafri@gmail.com>
|
build |
You seem to have missed my previous comment. Please add some test. |
Greptile OverviewGreptile SummaryThis PR fixes a bug in the GPU-accelerated Delta Lake scan with deletion vectors (DV). When
Confidence Score: 5/5
Important Files ChangedFile Analysis
Sequence DiagramsequenceDiagram
participant Delta as Delta Table (with DVs)
participant Plan as Query Plan
participant Prune as pruneFileMetadata
participant FSSE as GpuFileSourceScanExec
participant Output as Output Attributes
Delta->>Plan: Read partitioned table
Plan->>Plan: Add _tmp_metadata_row_index<br/>for DV filtering
Plan->>Prune: Match DV scan pattern
Prune->>FSSE: Filter _metadata from project list
Prune->>FSSE: Filter _tmp_metadata_row_index<br/>from requiredSchema
Prune->>FSSE: Filter _tmp_metadata_row_index<br/>from originalOutput (NEW)
FSSE->>Output: Split at requiredSchema.length
Output->>Output: Data attrs ++ Partition attrs<br/>(correctly positioned)
|
There was a problem hiding this comment.
Additional Comments (1)
-
integration_tests/src/main/python/delta_lake_test.py, line 170 (link)style: Unused import -
DeltaTableis imported but never used in this test.
2 files reviewed, 1 comment
|
build |
| USING DELTA | ||
| LOCATION '{data_path}' | ||
| PARTITIONED BY (region) | ||
| TBLPROPERTIES ('delta.enableDeletionVectors' = 'true') |
There was a problem hiding this comment.
This is an internal example that is prone to a single record per file where DVs are not necessary upon delete since the whole file can be dropped.
Please use the more robust example for regression test. You can rewrite in SQL if you like
from delta import DeltaTable
spark.range(1000).withColumnRenamed('id', 'l_id').join(spark.range(10)).write.partitionBy('l_id').format('delta').option('delta.enableDeletionVectors', True).save('/tmp/range_dvp4')
dt = DeltaTable.forPath(spark, '/tmp/range_dvp4')
dt.delete('id = 1')
dt.toDF().explain()
|
Can you also update the PR title and description to match with the updated change? |
|
@jihoonson @gerashegalov thank you for reviewing the PR. I have addressed all your concerns PTAL |
There was a problem hiding this comment.
Additional Comments (1)
-
integration_tests/src/main/python/delta_lake_test.py, line 178-179 (link)style: Trailing whitespace on line 178, and line 179 has 7 spaces instead of 8 for indentation.
2 files reviewed, 1 comment
|
build |
| data_path = spark_tmp_path + "/DELTA_DATA" | ||
|
|
||
| def create_delta(spark): | ||
| two_col_df(spark, int_gen, int_gen).coalesce(1).write.format("delta") \ |
There was a problem hiding this comment.
Is int_gen guaranteed to have a 0 that you are later deleting?
Is coalesce(1) the same as passing num_slices=1 to two_col_df ?
There was a problem hiding this comment.
0 is guaranteed to be present as it's a special_case in the IntegerGen
| .option("delta.enableDeletionVectors", "true") \ | ||
| .partitionBy("a").save(data_path) | ||
|
|
||
| spark.sql(f"DELETE FROM delta.`{data_path}` WHERE b = 0") |
There was a problem hiding this comment.
Should we assert that we deleted at least one row by looking at the result df returned by this statement?
There was a problem hiding this comment.
good idea. I think we should
| spark.sql(f"DELETE FROM delta.`{data_path}` WHERE b = 0") | ||
|
|
||
| def read_table(spark): | ||
| return spark.sql(f"SELECT * FROM delta.`{data_path}` ") |
There was a problem hiding this comment.
Alternatively to the above suggestions, can we assert the explain output includes DV-enabled scan with __delta_internal_is_row_deleted column?
There was a problem hiding this comment.
Additional Comments (1)
-
integration_tests/src/main/python/delta_lake_test.py, line 179-180 (link)style: Trailing whitespace on line 179 and inconsistent indentation (7 spaces instead of standard 8).
2 files reviewed, 1 comment
|
build |
### Description A recently introduced test in #13991 is irrelevant for DBR as we currently don't support Deletion Vectors on DBR. This PR skips the test on DBR and for versions of Spark that don't support Deletion Vectors ### Checklists - [ ] This PR has added documentation for new or modified features or behaviors. - [x] This PR has added new tests or modified existing tests to cover new code paths. (Please explain in the PR description how the new code paths are tested, such as names of the new/existing tests that cover them.) - [ ] Performance testing has been performed and its results are added in the PR description. Or, an issue has been filed with a link in the PR description. --------- Signed-off-by: Raza Jafri <raza.jafri@gmail.com>
Description
When returning output from
GpuFileSourceScanExec, we leave the temporary row_index column that is generated as part of the DV scan. The presence of this column breaks our assumption that partition columns follow immediately after the output column. This PR removes the_tmp_metadata_row_indexcolumn from the output.Checklists
(Please explain in the PR description how the new code paths are tested, such as names of the new/existing tests that cover them.)