MySQL vs MariaDB - "Using sort_union(index1,PRIMARY)"

Last year, I migrated from MariaDB to Percona for MySQL, while it was on version 8.0.33. Now we’re on version 8.0.36, and the same still happens, so I’d like to ask here.

I had a number of performance issues during the migration, for queries that worked well on MariaDB, which I had to optimize for MySQL. That’s expected, as both have diverged a lot since MariaDB’s fork. However, I’m not sure why there is a difference in this one I’m reporting.

Consider this SQL, which is of the format A or B or C or D (with an IN subquery in each):

SELECT 1 FROM `table1`
WHERE (`uid`="1234" AND `frid` IN (SELECT `table4`.`uid` FROM `table4` JOIN `table2` ON `table4`.`uid`=`table2`.`uid` AND `table2`.`col5` IN ("1", "2") WHERE `table4`.`id`="19581") AND NOT EXISTS (SELECT 1 FROM `table3` WHERE `uid`="1234" AND `frid`="6789") AND (`frid`="6789" OR `time`>1687123900))
OR (`frid`="1234" AND `uid` IN (SELECT `table4`.`uid` FROM `table4` JOIN `table2` ON `table4`.`uid`=`table2`.`uid` AND `table2`.`col5` IN ("1", "2") WHERE `table4`.`id`="19581") AND NOT EXISTS (SELECT 1 FROM `table3` WHERE `uid`="6789" AND `frid`="1234") AND (`uid`="6789" OR `time`>1687123900))
OR (`uid`="6789" AND `frid` IN (SELECT `table4`.`uid` FROM `table4` JOIN `table2` ON `table4`.`uid`=`table2`.`uid` AND `table2`.`col5` IN ("1", "2") WHERE `table4`.`id`="379") AND NOT EXISTS (SELECT 1 FROM `table3` WHERE `uid`="6789" AND `frid`="1234") AND (`frid`="1234" OR `time`>1687123900))
OR (`frid`="6789" AND `uid` IN (SELECT `table4`.`uid` FROM `table4` JOIN `table2` ON `table4`.`uid`=`table2`.`uid` AND `table2`.`col5` IN ("1", "2") WHERE `table4`.`id`="379") AND NOT EXISTS (SELECT 1 FROM `table3` WHERE `uid`="1234" AND `frid`="6789") AND (`uid`="1234" OR `time`>1687123900))
LIMIT 1

In MariaDB 10.8, this query was optimized, because of Using sort_union(frid,PRIMARY);:

However, in Percona 8.0.33 (and 8.0.36), it does a full table scan:

I tried adding a hint, but it seems to be 100% ignored (not sure if I’m doing it well?):

SELECT /*+ INDEX_MERGE(table1 frid,PRIMARY) */ 1 FROM ...

My optimizer_switch is the default:

index_merge=on,​index_merge_union=on,​index_merge_sort_union=on,​index_merge_intersection=on,​engine_condition_pushdown=on,​index_condition_pushdown=on,​mrr=on,​mrr_cost_based=on,​block_nested_loop=on,​batched_key_access=off,​materialization=on,​semijoin=on,​loosescan=on,​firstmatch=on,​duplicateweedout=on,​subquery_materialization_cost_based=on,​use_index_extensions=on,​condition_fanout_filter=on,​derived_merge=on,​use_invisible_indexes=off,​skip_scan=on,​hash_join=on,​subquery_to_derived=off,​prefer_ordering_index=on,​hypergraph_optimizer=off,​derived_condition_pushdown=on,​favor_range_scan=off

and so was in MariaDB, but quite different:

index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=off

Any ideas?

I ended up splitting the query into 4.
Doing a SELECT (q1), (q2), (q3), (q4) seems well optimized, reading much less rows than when using the index_merge, which is good/better.
But I’d like to understand why MySQL/Percona isn’t optimizing the original query above, though.

Thank you very much!

Have you found an explanation?
I have the same problem with index_merge, it never uses it no matter what configuration I set on optimizer_switch. Same with hints, they are ignored.

I haven’t looked further, after all the troubleshooting above and opening this thread. :slight_smile: