You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Add support for MapSort expression in Spark 4.0.0 #1941
Spark 4.0.0 adds a MapSort expression, which can be used in hash partitioning expressions. Comet will currently fall back to Spark if these expressions exist.
Some Updates:
I have a simple test to start with, which will produce _groupingmapsort.
val data = Seq(
| Map("a" -> 1, "b" -> 2),
| Map("a" -> 3, "b" -> 4),
| Map("b" -> 2, "a" -> 1)
| )
val df = data.toDF("map")
df.groupBy("map").count().show(false)
So far based on my understanding, it looks like - this will require some plumbing at the Parquet reader utils in Scala, because currently we only support primitive types but MapType is a complex type. I made some hack to bypass some type-checking, however, the Native.initColumnReader() expects primitiveTypeId. I have to understand how the MapType would translate to primitiveTypeId. The closest one at the moment seems to be parquet's BINARY physical type. So, thinking of passing BINARY type and annotating with MapKeyValueTypeAnnotation. However, I'm still trying to understand this piece of code, so I might be wrong. I will do some more experiments to have more clarity on this.
Some Updates: I have a simple test to start with, which will produce _groupingmapsort.
val data = Seq(
| Map("a" -> 1, "b" -> 2),
| Map("a" -> 3, "b" -> 4),
| Map("b" -> 2, "a" -> 1)
| )
val df = data.toDF("map")
df.groupBy("map").count().show(false)
So far based on my understanding, it looks like - this will require some plumbing at the Parquet reader utils in Scala, because currently we only support primitive types but MapType is a complex type. I made some hack to bypass some type-checking, however, the Native.initColumnReader() expects primitiveTypeId. I have to understand how the MapType would translate to primitiveTypeId. The closest one at the moment seems to be parquet's BINARY physical type. So, thinking of passing BINARY type and annotating with MapKeyValueTypeAnnotation. However, I'm still trying to understand this piece of code, so I might be wrong. I will do some more experiments to have more clarity on this.
I managed to scan the map-type by setting CometConf.COMET_NATIVE_SCAN_IMPL.key -> native_datafusion . Added map_sort UDF with return type as Map.
However, it looks like doing a group-by on the map-type is not possible at the moment. Native code throws error message like - Not yet implemented: not yet implemented: Map(...).
This error seems to be coming from Arrow. So, presently, we cannot use MapType for grouping, we might have to translate map to a more simple type. Will explore more on this.
managed to scan the map-type by setting CometConf.COMET_NATIVE_SCAN_IMPL.key -> native_datafusion . Added map_sort UDF with return type as Map.
Right. native_comet does not support complex types. You can also try with native_iceberg_compat.
For map_sort you could try an order by instead of a group by in your test query
managed to scan the map-type by setting CometConf.COMET_NATIVE_SCAN_IMPL.key -> native_datafusion . Added map_sort UDF with return type as Map.
Right. native_comet does not support complex types. You can also try with native_iceberg_compat. For map_sort you could try an order by instead of a group by in your test query
I doubled-checked applying orderby on mapType in Spark-4.0 and got,
The `sortorder` does not support ordering on type "MAP<STRING, INT>". SQLSTATE: 42K09;
I'm attempting if we can do some changes to the plan to use string-representation of map instead of map directly during groupby/shuffling. If this doesn't work correctly or turned out to be too convoluted, I will wait for the complex type support.
Essentially a Map type is a repeated group of key and value fields. Note however that both key and value can themselves be complex types as in this test file:
Eleven tests in CometColumnarShuffleSuite are currently skipped with assume(!isSpark40Plus) for this issue:
columnar shuffle on map [bool]
columnar shuffle on map [byte]
columnar shuffle on map [short]
columnar shuffle on map [int]
columnar shuffle on map [long]
columnar shuffle on map [float]
columnar shuffle on map [double]
columnar shuffle on map [date]
columnar shuffle on map [timestamp]
columnar shuffle on map [decimal]
columnar shuffle on map [string]
columnar shuffle on map [binary]
(12 tests total — the array element variant passes.)
On Spark 4, every failing test shows the same plan: CometShuffleExchangeExec is replaced by a plain Exchange with hashpartitioning(mapsort(_2#N), mapsort(_3#N), ...). Spark 4 wraps each map partitioning key with MapSort so that equal maps normalize to the same canonical key order before hashing. Comet's shuffle partitioning serde does not recognize MapSort, so native shuffle is rejected for every map-keyed shuffle.
Activity
rishvin commentedon Jul 13, 2025
I would like to work on this.
rishvin commentedon Jul 22, 2025
Some Updates:
I have a simple test to start with, which will produce
_groupingmapsort.So far based on my understanding, it looks like - this will require some plumbing at the Parquet reader utils in Scala, because currently we only support primitive types but
MapTypeis a complex type. I made some hack to bypass some type-checking, however, theNative.initColumnReader()expectsprimitiveTypeId. I have to understand how theMapTypewould translate toprimitiveTypeId. The closest one at the moment seems to be parquet'sBINARYphysical type. So, thinking of passingBINARYtype and annotating withMapKeyValueTypeAnnotation. However, I'm still trying to understand this piece of code, so I might be wrong. I will do some more experiments to have more clarity on this.rishvin commentedon Jul 24, 2025
I managed to scan the map-type by setting
CometConf.COMET_NATIVE_SCAN_IMPL.key -> native_datafusion. Addedmap_sortUDF with return type asMap.However, it looks like doing a group-by on the map-type is not possible at the moment. Native code throws error message like -
Not yet implemented: not yet implemented: Map(...).This error seems to be coming from Arrow. So, presently, we cannot use MapType for grouping, we might have to translate map to a more simple type. Will explore more on this.
parthchandra commentedon Jul 24, 2025
Right.
native_cometdoes not support complex types. You can also try withnative_iceberg_compat.For
map_sortyou could try anorder byinstead of agroup byin your test queryrishvin commentedon Jul 25, 2025
Thanks @parthchandra. We cannot use
order bybecause spark appliesMapSorteither for groupby or repartitioning using the following rules,InsertMapSortInRepartitioningExpression
InsertMapSortInGroupingExpression
I doubled-checked applying orderby on mapType in Spark-4.0 and got,
I'm attempting if we can do some changes to the plan to use string-representation of map instead of map directly during groupby/shuffling. If this doesn't work correctly or turned out to be too convoluted, I will wait for the complex type support.
parthchandra commentedon Jul 25, 2025
Oh well.
For Maps, you might want to look at the mapping of Spark's MapType to a Parquet Schema here:
datafusion-comet/common/src/main/scala/org/apache/spark/sql/comet/parquet/CometSparkToParquetSchemaConverter.scala
Line 254 in 320ce55
datafusion-comet/common/src/main/scala/org/apache/spark/sql/comet/parquet/CometSparkToParquetSchemaConverter.scala
Line 287 in 320ce55
Essentially a Map type is a repeated group of key and value fields. Note however that both key and value can themselves be complex types as in this test file:
datafusion-comet/spark/src/test/scala/org/apache/spark/sql/CometTestBase.scala
Line 719 in 320ce55
rishvin commentedon Aug 20, 2025
I have something working for
HashAggon map-type integrated withMapSort. Will open a PR soon.rishvin commentedon Aug 25, 2025
Opened #2221
rishvin commentedon Sep 11, 2025
Hi @andygrove / @parthchandra: Please see new updates here: #2381 (comment)
andygrove commentedon Apr 22, 2026
Eleven tests in
CometColumnarShuffleSuiteare currently skipped withassume(!isSpark40Plus)for this issue:columnar shuffle on map [bool]columnar shuffle on map [byte]columnar shuffle on map [short]columnar shuffle on map [int]columnar shuffle on map [long]columnar shuffle on map [float]columnar shuffle on map [double]columnar shuffle on map [date]columnar shuffle on map [timestamp]columnar shuffle on map [decimal]columnar shuffle on map [string]columnar shuffle on map [binary](12 tests total — the
array elementvariant passes.)On Spark 4, every failing test shows the same plan:
CometShuffleExchangeExecis replaced by a plainExchangewithhashpartitioning(mapsort(_2#N), mapsort(_3#N), ...). Spark 4 wraps each map partitioning key withMapSortso that equal maps normalize to the same canonical key order before hashing. Comet's shuffle partitioning serde does not recognizeMapSort, so native shuffle is rejected for every map-keyed shuffle.