[英]MySQL 5.7.36 Where Clause OR Operator not Short Circuiting
我搜索了所有紫色的 Google 鏈接,但沒有找到解決問題的方法。
據我所知,MySQL 不會在where子句中短路OR運算符。 很多搜索結果解釋了為什么會發生這種情況,但這實際上並不能幫助解決我的問題。
我們正在運行 MySQL 版本5.7.36 。
以下是查詢中性能差異的結果:
使用 OR 子句查詢( 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)
執行計划:
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)
不帶 OR 子句的查詢( 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)
執行計划:
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)
這個查詢是由 Spring JPA 生成的,因此沒有方便的方法來自己生成查詢。
嘗試添加另一個索引,但執行計划保持不變:
create index account_transaction__indextest
on account_transaction (description asc, datetime desc);
帶有附加索引的執行計划:
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)
SHOW CREATE TABLE
以便我們了解數據類型、索引等。EXPLAIN
似乎暗示某些索引以datetime
開頭。true
或1
或1=1
或... LIKE '%'
類的查詢。 它使優化器的工作更加困難。 顯然它分散了它“做正確的事”的注意力。description LIKE '%'
。 如果是這樣,您可以編寫一個錯誤報告來建議將其優化為 TRUE。 但它可能會被拒絕,因為這實際上可能被視為description IS NOT NULL
! 運行SHOW WARNINGS;
執行EXPLAIN
后。SELECT *
的EXPLAINs
和時間通常與SELECT COUNT(*)
完全不同。 選擇你想討論的; 不要混合它們。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.