Files
datastore/tests/performance/map_subcolumns_prewhere.xml
avogarandClaude Opus 4.6 0243158d48 Revert non-adjacent PREWHERE grouping to preserve evaluation order
Non-adjacent grouping could reorder predicates past intentional guards,
e.g. `PREWHERE tags['safe'] != '' AND value > 0 AND toUInt64(tags['unsafe']) > 0`
would pull the throwing conversion before the `value > 0` filter.

Revert to adjacent-only grouping in `tryBuildPrewhereSteps`. This is safe
because `MergeTreeWhereOptimizer` already groups subcolumns of the same
storage column together, so they arrive adjacent for the WHERE-to-PREWHERE
path.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-06-22 19:43:02 +00:00

147 lines
6.8 KiB
XML

<test>
<!-- Benchmarks Map subcolumn reads with optimize_functions_to_subcolumns enabled.
When multiple Map subcolumn conditions appear in PREWHERE, they should be grouped
into a single read step to avoid redundant deserialization of the same Map data.
Tests SELECT of multiple keys, count() with WHERE, and count() with PREWHERE
for both Wide and Compact part formats. -->
<settings>
<max_insert_threads>4</max_insert_threads>
<use_query_condition_cache>0</use_query_condition_cache>
</settings>
<!-- Wide part format -->
<create_query>
CREATE TABLE map_subcol_pw_wide (id UInt64, tags Map(String, String))
ENGINE = MergeTree ORDER BY id
SETTINGS min_bytes_for_wide_part = 0, min_rows_for_wide_part = 0
</create_query>
<!-- Compact part format -->
<create_query>
CREATE TABLE map_subcol_pw_compact (id UInt64, tags Map(String, String))
ENGINE = MergeTree ORDER BY id
SETTINGS min_bytes_for_wide_part = '10G', min_rows_for_wide_part = 1000000000
</create_query>
<fill_query>
INSERT INTO map_subcol_pw_wide
SELECT number AS id,
mapFromArrays(
arrayMap(i -> 'k' || toString(i), range(16)),
arrayMap(i -> toString(number + i), range(16))) AS tags
FROM numbers_mt(5000000)
</fill_query>
<fill_query>OPTIMIZE TABLE map_subcol_pw_wide FINAL SETTINGS mutations_sync=1</fill_query>
<fill_query>
INSERT INTO map_subcol_pw_compact
SELECT number AS id,
mapFromArrays(
arrayMap(i -> 'k' || toString(i), range(16)),
arrayMap(i -> toString(number + i), range(16))) AS tags
FROM numbers_mt(5000000)
</fill_query>
<fill_query>OPTIMIZE TABLE map_subcol_pw_compact FINAL SETTINGS mutations_sync=1</fill_query>
<!-- Wide: SELECT multiple keys -->
<query>
SELECT tags['k0'], tags['k1'], tags['k2'], tags['k3'],
tags['k4'], tags['k5'], tags['k6'], tags['k7'],
tags['k8'], tags['k9'], tags['k10'], tags['k11'],
tags['k12'], tags['k13'], tags['k14'], tags['k15']
FROM map_subcol_pw_wide
FORMAT Null
SETTINGS optimize_functions_to_subcolumns=1
</query>
<!-- Compact: SELECT multiple keys -->
<query>
SELECT tags['k0'], tags['k1'], tags['k2'], tags['k3'],
tags['k4'], tags['k5'], tags['k6'], tags['k7'],
tags['k8'], tags['k9'], tags['k10'], tags['k11'],
tags['k12'], tags['k13'], tags['k14'], tags['k15']
FROM map_subcol_pw_compact
FORMAT Null
SETTINGS optimize_functions_to_subcolumns=1
</query>
<!-- Wide: count() with WHERE -->
<query>
SELECT count() FROM map_subcol_pw_wide
WHERE tags['k0'] != '' AND tags['k1'] != '' AND tags['k2'] != '' AND tags['k3'] != ''
AND tags['k4'] != '' AND tags['k5'] != '' AND tags['k6'] != '' AND tags['k7'] != ''
AND tags['k8'] != '' AND tags['k9'] != '' AND tags['k10'] != '' AND tags['k11'] != ''
AND tags['k12'] != '' AND tags['k13'] != '' AND tags['k14'] != '' AND tags['k15'] != ''
SETTINGS optimize_functions_to_subcolumns=1, optimize_move_to_prewhere=0
</query>
<!-- Compact: count() with WHERE -->
<query>
SELECT count() FROM map_subcol_pw_compact
WHERE tags['k0'] != '' AND tags['k1'] != '' AND tags['k2'] != '' AND tags['k3'] != ''
AND tags['k4'] != '' AND tags['k5'] != '' AND tags['k6'] != '' AND tags['k7'] != ''
AND tags['k8'] != '' AND tags['k9'] != '' AND tags['k10'] != '' AND tags['k11'] != ''
AND tags['k12'] != '' AND tags['k13'] != '' AND tags['k14'] != '' AND tags['k15'] != ''
SETTINGS optimize_functions_to_subcolumns=1, optimize_move_to_prewhere=0
</query>
<!-- Wide: count() with PREWHERE -->
<query>
SELECT count() FROM map_subcol_pw_wide
PREWHERE tags['k0'] != '' AND tags['k1'] != '' AND tags['k2'] != '' AND tags['k3'] != ''
AND tags['k4'] != '' AND tags['k5'] != '' AND tags['k6'] != '' AND tags['k7'] != ''
AND tags['k8'] != '' AND tags['k9'] != '' AND tags['k10'] != '' AND tags['k11'] != ''
AND tags['k12'] != '' AND tags['k13'] != '' AND tags['k14'] != '' AND tags['k15'] != ''
SETTINGS optimize_functions_to_subcolumns=1
</query>
<!-- Compact: count() with PREWHERE -->
<query>
SELECT count() FROM map_subcol_pw_compact
PREWHERE tags['k0'] != '' AND tags['k1'] != '' AND tags['k2'] != '' AND tags['k3'] != ''
AND tags['k4'] != '' AND tags['k5'] != '' AND tags['k6'] != '' AND tags['k7'] != ''
AND tags['k8'] != '' AND tags['k9'] != '' AND tags['k10'] != '' AND tags['k11'] != ''
AND tags['k12'] != '' AND tags['k13'] != '' AND tags['k14'] != '' AND tags['k15'] != ''
SETTINGS optimize_functions_to_subcolumns=1
</query>
<!-- Table with an extra column to test WHERE optimizer grouping.
When Map subcolumn conditions are interleaved with another column in WHERE,
the optimizer should group Map conditions together to avoid redundant reads. -->
<create_query>
CREATE TABLE map_subcol_pw_mixed (id UInt64, tags Map(String, String), value UInt32)
ENGINE = MergeTree ORDER BY id
SETTINGS min_bytes_for_wide_part = 0, min_rows_for_wide_part = 0
</create_query>
<fill_query>
INSERT INTO map_subcol_pw_mixed
SELECT number AS id,
mapFromArrays(
arrayMap(i -> 'k' || toString(i), range(16)),
arrayMap(i -> toString(number + i), range(16))) AS tags,
number AS value
FROM numbers_mt(5000000)
</fill_query>
<fill_query>OPTIMIZE TABLE map_subcol_pw_mixed FINAL SETTINGS mutations_sync=1</fill_query>
<!-- WHERE with interleaved Map subcolumns and another column.
The optimizer should group all Map conditions together even though
the 'value' condition appears between them in the original WHERE. -->
<query>
SELECT count() FROM map_subcol_pw_mixed
WHERE tags['k0'] != '' AND tags['k1'] != '' AND tags['k2'] != '' AND tags['k3'] != ''
AND value > 0
AND tags['k4'] != '' AND tags['k5'] != '' AND tags['k6'] != '' AND tags['k7'] != ''
AND tags['k8'] != '' AND tags['k9'] != '' AND tags['k10'] != '' AND tags['k11'] != ''
AND tags['k12'] != '' AND tags['k13'] != '' AND tags['k14'] != '' AND tags['k15'] != ''
SETTINGS optimize_functions_to_subcolumns=1, move_all_conditions_to_prewhere=1
</query>
<drop_query>DROP TABLE IF EXISTS map_subcol_pw_wide</drop_query>
<drop_query>DROP TABLE IF EXISTS map_subcol_pw_compact</drop_query>
<drop_query>DROP TABLE IF EXISTS map_subcol_pw_mixed</drop_query>
</test>