Anil K created SPARK-60782:
------------------------------

             Summary: Pandas and Arrow cogroups pair groups wrongly when the 
two sides' grouping keys have different types
                 Key: SPARK-60782
                 URL: https://issues.apache.org/jira/browse/SPARK-60782
             Project: Spark
          Issue Type: Bug
          Components: SQL
    Affects Versions: 5.0.0
            Reporter: Anil K


A cogroup in PySpark checks only that both sides group by the same number of 
keys (SPARK-40601). It does not check or coerce their types, so one side can 
group by an {{INT}} and the other by a {{BIGINT}}:
{code:python}
left = spark.range(10).selectExpr("CAST(id AS INT) AS id", "'l' AS v")   # INT 
key
right = spark.range(10).selectExpr("id", "'r' AS w")                     # 
BIGINT key

def count(l, r):
    key = l["id"][0] if len(l) else r["id"][0]
    return pd.DataFrame({"id": [int(key)], "l": [len(l)], "r": [len(r)]})

left.groupby("id").cogroup(right.groupby("id")) \
    .applyInPandas(count, "id long, l long, r long").collect()
{code}
Every id should form one group with one row from each side, i.e. 10 groups. 
Measured on PySpark 4.3.0 in local mode, with 
{{spark.sql.shuffle.partitions=200}}:
||{{spark.sql.adaptive.enabled}}||{{spark.sql.adaptive.coalescePartitions.enabled}}||result||
|false|-|20 groups, none matched: each id is a left-only and a right-only group|
|true|false|20 groups, none matched|
|true|true|10 groups, all matched, since AQE coalesces the 10 rows into one 
partition|

So it returns wrong results with no error whenever AQE does not put both sides 
of a key into one partition, which is the case for data of any size.

{{FlatMapCoGroupsInPandasExec}} and {{FlatMapCoGroupsInArrowExec}} require each 
side to be clustered on its own keys, and {{EnsureRequirements}} 
hash-partitions each side on them. {{Murmur3Hash}} hashes an {{INT}} and a 
{{BIGINT}} differently: with 200 partitions, 5 :: INT goes to partition 66 and 
5 :: BIGINT to partition 68. So the two groups for one key value land in 
different partitions, and the function is called once with the left group and 
an empty right one, and once the other way round.

With {{spark.sql.sources.v2.bucketing.shuffle.enabled}} and a 
storage-partitioned side, the other side can instead be shuffled onto that 
side's layout, rebuilt over its own key. Then the query can fail, e.g. with a 
{{ClassCastException}} when the layout's {{bucket}} declares an {{INT}} and 
gets a {{BIGINT}}.

A join does not have this problem, since the analyzer coerces the two sides of 
an equi-join condition to one type.

A fix could coerce the two sides' grouping keys to a common type in 
{{flatMapCoGroupsInPandas}} and {{flatMapCoGroupsInArrow}}, as a join does, or 
reject keys of different types with a clear error, as SPARK-40601 does for a 
different number of keys.




--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to