Oracle优化——LIKE与索引(以%开头的LIKE会不走索引或走索引全扫描)

本文通过示例介绍了Oracle中LIKE操作符如何影响索引的使用。以%开头的LIKE表达式会导致全表扫描或不使用索引,而强制使用索引可能导致全索引扫描,效率较低。
这样会走索引范围扫描,因为这个表达式有前导性。
SH@ prod> set autotrace on
SH@ prod> select max(cust_credit_limit) , count(*) from customers_ne where cust_last_name like 'Vaugh%' ;

MAX(CUST_CREDIT_LIMIT)   COUNT(*)
---------------------- ----------
                 11000         81


Execution Plan
----------------------------------------------------------
Plan hash value: 3473995898

---------------------------------------------------------------------------------------------
| Id  | Operation                    | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |              |     1 |    16 |    13   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE              |              |     1 |    16 |            |          |
|   2 |   TABLE ACCESS BY INDEX ROWID| CUSTOMERS_NE |    61 |   976 |    13   (0)| 00:00:01 |
|*  3 |    INDEX RANGE SCAN      
<think>好的,我现在需要解决的问题是,当SQL查询中使用`LIKE '%1%'`这样的条件时,是否可以利用索引优化查询性能。用户之前已经询问过关于`LIKE '1%'`的优化方法,现在转向更广泛的情况,即中间有通配符的情况。我需要先回忆一下数据库索引的基本原理,特别是关于字符串前缀、后缀和中间匹配的情况。 首先,数据库索引,尤其是B树索引,通常最有效的是前缀匹配。例如,`LIKE '1%'`可以利用索引,因为索引是按顺序存储的,查询可以快速定位到以'1'开头的字符串。但是,当使用前导通配符如`LIKE '%1%'`时,情况就同了,因为数据库无法有效利用索引来快速定位,可能需要扫描,这会降低查询性能。 接下来,我需要考虑是否有其他类型的索引可以处理这种情况。例如,索引者反向索引。比如,在MySQL中,如果使用索引(FULLTEXT),可以处理更复杂的文本搜索,包括中间匹配。但用户的问题可能是在普通B树索引的情况下,是否可行。 另外,某些数据库支持函数索引,比如在字段上创建反向索引,将字符串反转后存储,这样查询`LIKE '%1'`可以转换为`LIKE '1%'`在反转后的字段上,从而利用索引。但这种方法需要预先处理数据,并且查询也需要相应调整。 还需要考虑覆盖索引的可能性,即索引包含所有需要的列,避免回表操作。但即使如此,如果查询条件本身无法有效使用索引,覆盖索引可能也无法带来性能提升。 此外,用户可能想知道,当必须使用`LIKE '%1%'`时,有哪些优化策略,比如使用更高效的文检索工具(如Elasticsearch),者数据预处理,比如将字符串分词存储,者使用触发器维护一个反向的字段。 另外,需要提到数据库的具体实现差异,比如MySQL、PostgreSQL等对LIKE子句和索引的支持可能同,可能需要具体分析。但用户的问题没有指定数据库类型,所以需要一般性的回答。 最后,总结可能的优化方法,包括使用索引、反向索引、函数索引(如果支持),者应用层的优化,如缓存结果、分页查询减少数据量等。同时,需要指出即使无法有效使用索引,合理的索引策略和查询优化仍能部分提升性能,比如减少查询涉及的字段,避免必要的连接等。 需要注意的是,用户之前的问题已经涉及了LEFT JOIN改为INNER JOIN的优化,所以在这里可能需要强调,当LIKE条件无法利用索引时,其他优化手段的重要性,比如减少JOIN的数量优化WHERE子句中的其他条件。 另外,要提醒用户,EXPLAIN命令是分析查询执行计划的关键工具,通过查看执行计划可以确认索引是否被使用,以及是否存在扫描等问题。 最后,要确保回答结构清晰,分点说明,让用户能够逐步理解同的优化策略及其适用场景。</think>当 SQL 查询中使用 **`LIKE '%1%'`**(即模糊匹配字符串中任意位置包含 `1` 的情况),能否利用索引取决于数据库的类型、索引的设计以及字段的具体特性。以下是详细的解释和优化建议: -- ### **1. 为什么 `LIKE '%1%'` 通常无法直接利用索引?** - **B树索引的局限性** 大多数数据库(如 MySQL、PostgreSQL)默认使用 B树索引,其优势在于**前缀匹配**(如 `LIKE '1%'`)。但 `LIKE '%1%'` 需要扫描整个字符串的任意位置是否包含 `1`,B树索引无法高效支持这种模式。 - **扫描的风险** 如果没有合适的索引,数据库可能需要对整个字段值逐行扫描,导致性能下降(尤其是大表)。 --- ### **2. 可能的优化方法** #### **(1) 使用索引(FULLTEXT)** - **适用场景**:高频的模糊匹配查询(如搜索功能)。 - **实现方式**: ```sql -- 创建索引(以 MySQL 为例) ALTER TABLE table_name ADD FULLTEXT INDEX idx_content (column_name); -- 查询使用索引 SELECT * FROM table_name WHERE MATCH(column_name) AGAINST('+1' IN BOOLEAN MODE); -- 匹配包含 '1' 的内容 ``` - **优势**:索引专为文本搜索设计,支持高效的关键词匹配。 - **限制**:仅适用于文本字段,且需数据库支持(如 MySQL 的 `FULLTEXT`,PostgreSQL 的 `GIN` 索引)。 --- #### **(2) 反向索引(Reverse Index)** - **适用场景**:后缀匹配(如 `LIKE '%1'`),但也可辅助中间匹配。 - **实现方式**: 1. 存储字段的反向值(如 `'abc123'` 存为 `'321cba'`)。 2. 对反向字段创建索引,查询时反转条件: ```sql -- 原查询:LIKE '%1%' -- 反转后查询:LIKE '1%' OR LIKE '%1'(需结合业务逻辑拆分) SELECT * FROM table_name WHERE original_column LIKE '%1%'; -- 改为反向字段查询(示例): SELECT * FROM table_name WHERE reversed_column LIKE '1%' -- 匹配原字段中以 '1' 结尾的内容 OR reversed_column LIKE '%1'; -- 匹配原字段中以 '1' 开头的内容 ``` - **优势**:将部分中间匹配转为前缀后缀匹配,可能利用索引。 - **限制**:需要额外存储和更新反向字段,逻辑复杂。 --- #### **(3) 函数索引(Function-Based Index)** - **适用场景**:数据库支持函数索引时(如 Oracle、PostgreSQL)。 - **实现方式**: ```sql -- PostgreSQL 示例:创建小写化索引 CREATE INDEX idx_lower_column ON table_name (LOWER(column_name)); -- 查询时使用函数匹配 SELECT * FROM table_name WHERE LOWER(column_name) LIKE '%1%'; ``` - **优势**:可对字段处理后的值建立索引,支持复杂查询。 - **限制**:依赖数据库支持,且需匹配函数逻辑。 --- #### **(4) 覆盖索引 + 减少回表** - **适用场景**:查询仅需索引中的字段,无需回查主表。 - **实现方式**: 创建包含查询所需字段的联合索引,如: ```sql -- 假设需要返回 column_a 和 column_b CREATE INDEX idx_covering ON table_name (target_column, column_a, column_b); -- 查询时仅访问索引 SELECT column_a, column_b FROM table_name WHERE target_column LIKE '%1%'; ``` - **优势**:避免回表操作,减少 I/O。 - **限制**:需查询字段部在索引中,且索引体积可能较大。 --- ### **3. 其他优化策略** - **分页缓存**:对高频查询结果缓存,减少数据库压力。 - **数据预处理**: 将字段拆分为分词(如 `'abc123'` 拆为 `['abc', '123']`),单独存储并建立索引。 - **使用外部搜索引擎**: 对海量模糊匹配场景,将数据同步到 Elasticsearch 等搜索引擎,利用倒排索引加速查询。 --- ### **4. 执行计划验证** 无论采用哪种方法,务必使用 `EXPLAIN` 分析执行计划,确认索引是否生效: ```sql EXPLAIN SELECT * FROM table_name WHERE column LIKE '%1%'; ``` 重点关注: - `type` 列是否为 `index`(索引扫描 `range`(范围扫描)。 - `Extra` 列是否出现 `Using where; Using index`(覆盖索引生效)。 --- ### **总结** - **`LIKE '%1%'` 默认难以利用 B树索引**,但可通过索引、反向索引、函数索引覆盖索引间接优化。 - **优先考虑业务需求**:是否真的需要任意位置模糊匹配?能否改用前缀匹配(`LIKE '1%'`)? - **权衡成本和收益**:复杂的优化方案可能增加维护成本,需结合查询频率和数据规模选择。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值