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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值