Skip to content

Commit 3d3cf6b

Browse files
adriangbclaude
andcommitted
Add a ClickBench extended query for the shape this rule now rewrites
No benchmark in the repository exercises the path this branch opens, so a benchmark run against it must report zero change. `SingleDistinctToGroupBy` needs exactly one distinct argument, so extended q0, q1 and q2 are out on their own. Standard q8, q10, q11 and q13 hold a lone distinct aggregate that `main` already rewrites. q9 carries an `AVG`, which the rule has never accepted. That leaves q22, the one query that reaches the new gate, and its `COUNT(DISTINCT "UserID")` is over an `Int64`, which has a specialized `GroupsAccumulator` and so never lands on `GroupsAccumulatorAdapter`. Extended q14 is that missing shape: a single `COUNT(DISTINCT <string>)` next to a non-distinct `COUNT(*)`, grouped by a high cardinality string. The distinct argument has no specialized accumulator, so the unrewritten plan builds one boxed `Accumulator`, and one hash table, for every group. Extended queries are discovered from the directory, so this needs no change to the runner. Co-Authored-By: Claude Opus 5 <[email protected]>
1 parent e0e5a8c commit 3d3cf6b

2 files changed

Lines changed: 38 additions & 0 deletions

File tree

‎benchmarks/queries/clickbench/README.md‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,35 @@ WHERE "URL" < 'zzzz';
261261
```
262262

263263

264+
### Q14: Grouped `COUNT(DISTINCT <string>)` beside a non-distinct `COUNT(*)`
265+
266+
**Question**: "For the top 10 search phrases by hit count, how many distinct
267+
mobile phone models were used?"
268+
269+
**Important Query Properties**: A single `COUNT(DISTINCT)` over a high
270+
cardinality string, next to a non-distinct `COUNT(*)`, grouped by a high
271+
cardinality string.
272+
273+
No query in the standard suite has this shape. `SingleDistinctToGroupBy`
274+
rewrites a lone distinct aggregate into a two phase group by, which is what
275+
keeps it off `GroupsAccumulatorAdapter` and its one boxed `Accumulator`, and so
276+
one hash table, for every group. Q8, Q10, Q11 and Q13 of the standard suite are
277+
already rewritten because their distinct aggregate stands alone. Q22 is the only
278+
standard query that pairs a lone distinct aggregate with a non-distinct count,
279+
and its distinct argument is an `Int64`, which has a specialized
280+
`GroupsAccumulator` and therefore never reaches the adapter. `COUNT(DISTINCT)`
281+
has a specialized accumulator for the integer types and for no other type, so a
282+
string argument is the case that does.
283+
284+
```sql
285+
SELECT "SearchPhrase", COUNT(*) AS c, COUNT(DISTINCT "MobilePhoneModel") AS models
286+
FROM hits
287+
WHERE "SearchPhrase" <> ''
288+
GROUP BY "SearchPhrase"
289+
ORDER BY c DESC
290+
LIMIT 10;
291+
```
292+
264293

265294

266295
## Data Notes
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
-- Must set for ClickBench hits_partitioned dataset. See https://github.com/apache/datafusion/issues/16591
2+
-- set datafusion.execution.parquet.binary_as_string = true
3+
4+
-- A grouped COUNT(DISTINCT <string>) beside a non-distinct COUNT(*). No query in
5+
-- the standard suite has this shape: q22 is the only one that pairs a lone
6+
-- distinct aggregate with a non-distinct count, and its distinct argument is an
7+
-- Int64, which has a specialized GroupsAccumulator. A string argument has none,
8+
-- so one boxed Accumulator, and one hash table, is built for every group.
9+
SELECT "SearchPhrase", COUNT(*) AS c, COUNT(DISTINCT "MobilePhoneModel") AS models FROM hits WHERE "SearchPhrase" <> '' GROUP BY "SearchPhrase" ORDER BY c DESC LIMIT 10;

0 commit comments

Comments
 (0)