@@ -1145,123 +1145,16 @@ adjacent chunks at RG boundaries.
11451145./bench.sh run sort_pushdown_inexact_overlap
11461146```
11471147
1148- ## Dictionary vs Utf8View Encoding Sweep
1149-
1150- ` dict_encoding_sweep ` compares ` Dictionary<Int32, Utf8> ` against ` Utf8View ` for
1151- the same operator across a cardinality sweep. Most groups generate two
1152- in-memory tables (one per encoding) that share values, SQL text, and seed. The
1153- ` parquet_scan ` group instead writes the same rows with both ` PLAIN ` and
1154- ` RLE_DICTIONARY ` physical encodings, then scans each file as both Arrow output
1155- representations. File generation is outside the timed region and the harness
1156- uses a neutral ` Utf8 ` writer schema so neither requested output representation
1157- is inherited from Parquet metadata. It verifies every data page has the
1158- requested physical encoding before recording results.
1159-
1160- Warmup and timed iterations are interleaved between Arrow output encodings so
1161- cache and thermal state stay symmetric. Median / min / p25 / p75 runtimes
1162- (nanoseconds) are appended to a CSV.
1163-
1164- The intent is to make it easy for other engineers to reproduce where dictionary
1165- encoding wins, where it loses, and at which NDV it crosses over, without
1166- touching the harness itself.
1167-
1168- ### Operator groups
1169-
1170- Pass ` --group ` to pick one of:
1171-
1172- | Group | Queries |
1173- | -------| ---------|
1174- | ` scan ` | ` scan_k ` , ` scan_all ` , ` scan_count_star ` , ` scan_count_k ` |
1175- | ` parquet_scan ` | ` scan_k ` , ` scan_all ` ; runs the ` PLAIN ` /` RLE_DICTIONARY ` × ` Utf8View ` /dictionary matrix |
1176- | ` filter ` | ` filter_eq ` , ` filter_ne ` , ` filter_in10 ` , ` filter_like_prefix ` , ` filter_gt ` , ` filter_1pct_group ` |
1177- | ` project ` | ` proj_length ` , ` proj_substr ` , ` proj_upper ` , ` proj_concat ` , ` proj_case_like ` |
1178- | ` aggregation ` | ` agg_count_distinct_k ` , ` agg_group_count_k ` , ` agg_group_sum_v_k ` , ` agg_group_count_kw ` , ` agg_having_k ` |
1179- | ` sort ` | ` sort_k ` , ` sort_k_desc ` , ` sort_k_limit_1000 ` , ` sort_kw ` , ` sort_v_by_k ` |
1180- | ` join ` | ` join_inner ` , ` join_inner_project ` , ` join_left ` , ` join_semi ` , ` join_anti_half ` |
1181- | ` limit ` | ` limit_k_100 ` , ` limit_k_1k ` , ` limit_k_10k ` , ` limit_all_1k ` , ` limit_offset_50k ` |
1182- | ` repartition ` | ` repart_group_k ` , ` repart_hash_join ` , ` repart_project_k ` |
1183- | ` coalesce_batches ` | ` cb_filter_eq ` , ` cb_filter_project ` , ` cb_filter_group ` |
1184- | ` coalesce_partitions ` | ` cp_scan_k ` , ` cp_count_star ` , ` cp_sum_v ` |
1185- | ` spm ` | ` spm_sort_k ` , ` spm_sort_k_limit ` , ` spm_sort_v_by_k ` |
1186-
1187- Narrow to one query with ` --query <id> ` .
1148+ ## Parquet RLE dictionary scan
11881149
1189- ### Running
1190-
1191- ``` bash
1192- # build release binary (one time)
1193- cargo build --release --bin dict_encoding_sweep -p datafusion-benchmarks
1194-
1195- # single cell: filter group, 1M rows, sweep over NDVs
1196- ./target/release/dict_encoding_sweep \
1197- --group filter --rows 1000000 \
1198- --ndvs 10,100,500,1000,4000,8192 \
1199- --iters 15 --warmups 3 \
1200- --output /tmp/dict_sweep/filter_1m.csv
1201- ```
1202-
1203- For scan-level Parquet decoding, one invocation produces four rows per query
1204- and NDV: ` PLAIN→Utf8View ` , ` PLAIN→Dictionary ` ,
1205- ` RLE_DICTIONARY→Utf8View ` , and ` RLE_DICTIONARY→Dictionary ` .
1206-
1207- ``` bash
1208- ./target/release/dict_encoding_sweep \
1209- --group parquet_scan --query scan_k --rows 1000000 \
1210- --ndvs 10,100,500,1000,2000,4000,8192 \
1211- --iters 15 --warmups 3 \
1212- --output /tmp/dict_sweep/parquet_scan_1m.csv
1213- ```
1214-
1215- The generated Parquet files are uncompressed so the measurements emphasize
1216- page decoding and Arrow array construction. ` k ` is the only column whose
1217- physical encoding changes. An explicit target schema requests both Arrow
1218- representations from both files, making source encoding and output
1219- representation independent axes. Focused coverage also verifies the four
1220- physical plans decode directly in ` DataSourceExec ` , without a projection cast
1221- between ` Utf8View ` and dictionary arrays.
1222-
1223- For a Criterion target suitable for the benchmark bot, the following command
1224- compares native ` Utf8View ` and dictionary output from an ` RLE_DICTIONARY `
1225- Parquet source across NDVs 1 through 500,000:
1150+ This Criterion target compares ` Utf8View ` and ` Dictionary<Int32, Utf8> ` output
1151+ from the same ` RLE_DICTIONARY ` Parquet data at NDVs from 1 through 500,000:
12261152
12271153``` bash
12281154cargo bench -p datafusion-benchmarks --bench parquet_rle_dictionary_scan
12291155```
12301156
1231- The target fixes the input at 1,000,000 rows of 16-byte strings in two
1232- 500,000-row groups. It verifies the physical page encoding and rejects plans
1233- that insert a representation cast above ` DataSourceExec ` .
1234-
1235- Useful flags:
1236-
1237- | Flag | Default | Notes |
1238- | ------| ---------| -------|
1239- | ` --group ` | required | Operator group (see table above). |
1240- | ` --query ` | all | Restrict to a single query id within the group. |
1241- | ` --rows ` | required | Rows in the generated table. |
1242- | ` --ndvs ` | required | Comma-separated distinct-value counts to sweep. |
1243- | ` --width ` | ` 16 ` | Fixed byte width per value. |
1244- | ` --nulls ` | ` 0.0 ` | Null fraction in column ` k ` . |
1245- | ` --batch-size ` | ` 8192 ` | Session + record-batch size. |
1246- | ` --target-partitions ` | ` 1 ` | Set ` >1 ` to force ` RepartitionExec ` nodes. |
1247- | ` --dict-chunk ` | ` 500000 ` | Rows per shared dictionary values-array chunk; also the Parquet row-group size for ` parquet_scan ` . |
1248- | ` --iters ` | ` 15 ` | Timed iterations per cell per encoding. |
1249- | ` --warmups ` | ` 3 ` | Untimed warmup iterations per cell per encoding. |
1250-
1251- ### CSV schema
1252-
1253- The output CSV uses one row per ` (encoding, cell) ` . Columns:
1254-
1255- ```
1256- git_sha, group, query_id, source_encoding, encoding, rows, ndv, width_bytes, null_rate,
1257- batch_size, dict_chunk_rows, process_id,
1258- median_ns, min_ns, p25_ns, p75_ns, iters, note
1259- ```
1260-
1261- ` source_encoding ` is ` memory ` , ` parquet_plain ` , or
1262- ` parquet_rle_dictionary ` . Parquet rows include the generated file size in
1263- ` note ` .
1264-
1265- Pair the two rows for the same cell by `(group, query_id, rows, ndv,
1266- width_bytes, null_rate, batch_size, dict_chunk_rows, source_encoding)` and divide
1267- ` dict.median_ns / view.median_ns ` to get the per-cell speedup.
1157+ Each case scans 1,000,000 16-byte strings in two 500,000-row groups. It covers
1158+ both annotated UTF-8 and unannotated binary sources, verifies the physical page
1159+ encoding, and rejects plans that insert a representation cast above
1160+ ` DataSourceExec ` .
0 commit comments