I have searched all my Google links purple and found no solution to my problem.
From what I can tell MySQL is NOT short circuiting the OR operator in a where clause. A lot of search results explain why this could happen, but that does not practically help solve my problem.
We are running MySQL version 5.7.36.
Here is the results of the performance difference in the query:
Query with OR clause (2 s 761 ms):
select count(*) from account_transaction
where (true or description like '%')
and datetime between '2022-05-19 00:00:00' and '2022-05-26 00:00:00'
[2022-05-27 08:28:36] 1 row retrieved starting from 1 in 2 s 787 ms (execution: 2 s 761 ms, fetching: 26 ms)
Execution plan:
mysql> explain select count(*) from account_transaction
-> where (true or description like '%')
-> and datetime between '2022-05-19 00:00:00' and '2022-05-26 00:00:00';
+----+-------------+---------------------+------------+------+----------------------------------+------+---------+------+---------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------------------+------------+------+----------------------------------+------+---------+------+---------+----------+-------------+
| 1 | SIMPLE | account_transaction | NULL | ALL | account_transaction_datetime_idx | NULL | NULL | NULL | 1172455 | 19.69 | Using where |
+----+-------------+---------------------+------------+------+----------------------------------+------+---------+------+---------+----------+-------------+
1 row in set, 1 warning (0.03 sec)
Query without OR clause (267ms):
select count(*) from account_transaction
where (true)
and datetime between '2022-05-19 00:00:00' and '2022-05-26 00:00:00'
[2022-05-27 08:26:09] 1 row retrieved starting from 1 in 286 ms (execution: 267 ms, fetching: 19 ms)
Execution plan:
mysql> explain select count(*) from account_transaction
-> where (true)
-> and datetime between '2022-05-19 00:00:00' and '2022-05-26 00:00:00';
+----+-------------+---------------------+------------+-------+----------------------------------+----------------------------------+---------+------+--------+----------+--------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------------------+------------+-------+----------------------------------+----------------------------------+---------+------+--------+----------+--------------------------+
| 1 | SIMPLE | account_transaction | NULL | range | account_transaction_datetime_idx | account_transaction_datetime_idx | 6 | NULL | 230898 | 100.00 | Using where; Using index |
+----+-------------+---------------------+------------+-------+----------------------------------+----------------------------------+---------+------+--------+----------+--------------------------+
1 row in set, 1 warning (0.00 sec)
This query is generated by Spring JPA and therefore no convenient way to generate the query ourselves.
Tried adding another index, but the execution plan remains the same:
create index account_transaction__indextest
on account_transaction (description asc, datetime desc);
Execution plan with additional index:
mysql> explain select * from account_transaction
-> where (true or description like '%')
-> and datetime between '2022-05-19 00:00:00' and '2022-05-26 00:00:00'
-> ;
+----+-------------+---------------------+------------+------+----------------------------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------------------+------------+------+----------------------------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | account_transaction | NULL | ALL | account_transaction_datetime_idx | NULL | NULL | NULL | 160 | 80.62 | Using where |
+----+-------------+---------------------+------------+------+----------------------------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)