对比Oracle和MySQL索引对于like的支持,MySQL一言难尽啊...
MySQL版本:8.0.36
Oracle版本:11.2.0.4.0
MySQL: | Oracle:
(root@localhost 09:44:08) [zkm](673009)> select * from test; | 09:52:11 ZKM@test(1076)> select * from test;
+------+-----------+ |
| id | name | | ID NAME
+------+-----------+ | ---------- -------------------------
| 1 | aaabbbccc | | 1 aaabbbccc
| 2 | dddeeefff | | 2 dddeeefff
| 3 | a b c | | 3 a b c
+------+-----------+ |
3 rows in set (0.01 sec) | Elapsed: 00:00:00.00
| 09:52:38 ZKM@test(1076)> create index idx_t_name on test(name);
(root@localhost 09:44:11) [zkm](673009)> create index idx_t_name on test(name); |
Query OK, 0 rows affected (0.26 sec) | Index created.
Records: 0 Duplicates: 0 Warnings: 0 |
| Elapsed: 00:00:00.02
现有SQL语句如下:
再Oracle和MySQL中正常无法自动走索引。
select * from test where name like '%ccc';
现在如果使用hint进行强制走索引操作,Oracle是支持的,但是MySQL就无法实现。。防。
https://www.cnblogs.com/PiscesCanon/p/18260833
MySQL强制走索引:
(root@localhost 16:28:50) [zkm](721306)> explain select * from test force index(idx_t_name) where name like '%ccc';
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | test | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 33.33 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.12 sec)
PS:使用如下hint结果一样:
Oracle强制走索引:
10:00:52 ZKM@test(1076)> explain plan for select /*+ index(test(name)) */ * from test where name like '%ccc';
Explained.
Elapsed: 00:00:00.00
10:01:06 ZKM@test(1076)> select * from table(dbms_xplan.display());
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------
Plan hash value: 3081316380
------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 25 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| TEST | 1 | 25 | 2 (0)| 00:00:01 |
|* 2 | INDEX FULL SCAN | IDX_T_NAME | 1 | | 1 (0)| 00:00:01 |
------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("NAME" IS NOT NULL AND "NAME" LIKE '%ccc')
对于where谓词条件中,reserve(name) like reserve('%ccc')的情况一样:
MySQL和Oracle都删除索引,并重新创建函数索引如下:
create index idx_t_name on test((reverse(name)));
MySQL依然无法使用索引,Oracle可以:
MySQL:
(root@localhost 16:34:17) [zkm](721306)> explain select * from test force index(idx_t_name) where reverse(name) like reverse('%ccc');
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | test | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 100.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
PS:以下两种方式均不行
explain select * from test use index(idx_t_name) where reverse(name) like reverse('%ccc');
explain select /*+ index(test idx_t_name) */ * from test where reverse(name) like reverse('%ccc');
Oracle:
10:52:46 ZKM@test(1076)> explain plan for select * from test where reverse(name) like reverse('%ccc');
Explained.
Elapsed: 00:00:00.01
10:55:06 ZKM@test(1076)> select * from table(dbms_xplan.display());
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------
Plan hash value: 2114388309
------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 37 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| TEST | 1 | 37 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | IDX_T_NAME | 1 | | 1 (0)| 00:00:01 |
------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access(REVERSE("NAME") LIKE 'ccc%')
filter(REVERSE("NAME") LIKE 'ccc%')
哎,优化时候遇到的问题。
只能跟业务讨论然后改SQL了。