对比Oracle和MySQL索引对于like的支持,MySQL一言难尽啊...

 

对比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了。

 

posted @ 2024-06-21 16:37  PiscesCanon  阅读(13)  评论(0编辑  收藏  举报