Yaoxuan Wu created SPARK-60600:
----------------------------------

             Summary: approx_top_k returns a count below the exact count when a 
partial sketch was purged to zero items
                 Key: SPARK-60600
                 URL: https://issues.apache.org/jira/browse/SPARK-60600
             Project: Spark
          Issue Type: Bug
          Components: SQL
    Affects Versions: 4.1.1, 4.2.0
            Reporter: Yaoxuan Wu


{code:python}
# two partitions: [0, 0, 0, 0, 0, 0, 0] and [0, 1, 2, 3, 4, 5, 6]; value 0 
occurs 8 times
spark.range(0, 14, 1, 2).selectExpr("CASE WHEN id < 7 THEN 0 ELSE id - 7 END AS 
v").createOrReplaceTempView("t")

spark.sql("SELECT approx_top_k(v, 1, 2) FROM t").collect()
# [Row(approx_top_k(v, 1, 2)=[Row(item=0, count=7)])]   expected count >= 8
spark.sql("SELECT approx_top_k(v, 1, 2) FROM (SELECT /*+ COALESCE(1) */ * FROM 
t)").collect()
# [Row(approx_top_k(v, 1, 2)=[Row(item=0, count=8)])]
{code}
The count Spark reports is {{ItemsSketch.getEstimate(item)}} for items from 
{{getFrequentItems(NO_FALSE_POSITIVES)}} ({{ApproxTopKAggregates.scala}}). For 
a tracked item, {{getEstimate}} is {{itemCount + offset}}, the same value as 
{{getUpperBound(item)}}, which DataSketches documents as "a number which is 
guaranteed to be no smaller than the real frequency". So a count of 7 for an 
item that occurs 8 times is wrong: the second partition's contribution was 
lost. The same through {{approx_top_k_accumulate}} / {{approx_top_k_combine}} / 
{{approx_top_k_estimate}}.

Cause: the second partition's 7 distinct values (count 1 each) make its 
{{ItemsSketch}} (maxItemsTracked 2, map capacity 6) purge every counter: it 
keeps the subtracted count in its offset but has no active items. In 
datasketches-java 6.2.0 (Spark's {{datasketches.version}}, also on master) 
{{ItemsSketch.isEmpty()}} is {{getNumActiveItems() == 0}}, so {{merge(other)}} 
returns early ({{if (other.isEmpty()) return this;}}) and {{toByteArray()}} 
writes the empty image; the offset and stream weight of that partial sketch are 
dropped in {{ApproxTopKAggregateBuffer.merge}} / {{serialize}}. This is fixed 
upstream by apache/datasketches-java#770 ("Frequent items: empty means zero 
stream weight, not zero active items", merged 2026-09-24, not yet released). 
Spark needs that release, or a workaround in {{ApproxTopKAggregateBuffer}} that 
merges / serializes sketches with a non-zero stream length explicitly.

Reproduces on 4.1.1 and 4.2.0.




--
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