隐式转换引起的索引失效

                     隐式转换引起的索引失效

SQL> create table test1 (userid varchar2(10));

Table created.

SQL> select * from test1;

no rows selected

SQL> insert into test1  select object_id from dba_objects;

72693 rows created.

SQL> create index id_idx on test1 (userid);

Index created.

SQL> set autotrace trace

SQL> select * from test1 where userid=2;            --条件是number类型


Execution Plan
----------------------------------------------------------
Plan hash value: 4122059633

---------------------------------------------------------------------------
| Id  | Operation         | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |       |     1 |     7 |    33   (4)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| TEST1 |     1 |     7 |    33   (4)| 00:00:01 |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter(TO_NUMBER("USERID")=2)

Note
-----
   - dynamic sampling used for this statement (level=2)


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
        116  consistent gets
          0  physical reads
          0  redo size
        523  bytes sent via SQL*Net to client
        523  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

SQL> select * from test1 where userid='2';           --加上引号后变成字符类型


Execution Plan
----------------------------------------------------------
Plan hash value: 1357208269

---------------------------------------------------------------------------
| Id  | Operation        | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT |        |     1 |     7 |     1   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| ID_IDX |     1 |     7 |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("USERID"='2')

Note
-----
   - dynamic sampling used for this statement (level=2)


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          3  consistent gets
          0  physical reads
          0  redo size
        523  bytes sent via SQL*Net to client
        523  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/26655292/viewspace-753368/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/26655292/viewspace-753368/

### MySQL 紗引失效原因及解决方案 #### 一、索引失效的主要原因 MySQL 的索引机制在某些特定条件下可能会失效,这会对查询性能造成严重影响。以下是常见的索引失效场景及其背后的原因: 1. **未遵循最左前缀匹配原则** 如果复合索引定义为 `(age, name)`,那么只有当查询条件满足 `age` 列时,才能继续利用后续列的索引。如果查询条件跳过了第一个字段,则整个索引将失效[^1]。 2. **使用函数或表达操作索引列** 当 SQL 中对索引列应用了函数或者复杂的表达运算时,MySQL 将无法直接通过索引来定位数据。例如,在查询中写入 `WHERE YEAR(date_column) = 2023` 或者 `WHERE ABS(value) > 100` 都会导致索引失效。 3. **的类型转换** 数据类型的不一致也会引发索引失效问题。比如,字符串与整数之间的比较可能导致 MySQL 自动执行类型转换,从而破坏原有的索引结构。 4. **范围查询的影响** 范围查询(如 `<`, `>`, `BETWEEN`)会使后续的索引字段失去作用。例如,在复合索引 `(age, name)` 上运行 `WHERE age=18 AND name>'xx'` 时,虽然可以使用 `age` 进行过滤,但由于存在范围条件,`name` 字段上的部分索引则不会被启用[^3]。 5. **特殊关键字引起的索引失效** 使用诸如 `NOT IN` 和 `NOT EXISTS` 关键字可能阻止优化器有效利用现有索引。这是因为这些操作符通常涉及全表扫描来验证不存在性约束[^2]。 #### 二、针对索引失效的具体解决办法 为了提高数据库查询效率并减少因索引失效带来的负面影响,可以从以下几个方面着手改进: 1. **调整查询逻辑以适应最左前缀规则** 修改 SQL 查询使其严格遵守复合索引中最左侧字段优先的原则。必要时重新设计索引顺序以便更好地支持实际业务需求。 2. **避免不必要的计算和转换** 不要随意修改索引列的内容形;尽量保持原始状态参与比较运算。可以通过创建额外的辅助列存储预处理后的值来进行替代性的高效检索。 3. **合理设置数据类型一致性** 确保所有涉及到的操作对象具有相同的数据类型描述,防止意外发生强制类型转化现象干扰正常工作流程。 4. **考虑覆盖索引策略** 所谓“覆盖索引”,是指所选中的索引包含了所需的所有信息而无需回溯到原记录文件读取更多细节。这样做的好处是可以显著降低 I/O 成本提升整体表现水平。 5. **改写复杂子查询** 对于那些容易引起全面遍历的情况——特别是含有否定型集合成员测试 (`NOT IN`) 的场合下——尝试重构相关表述方,采用连接(join)或其他更优算法代替原有实现方案。 ```sql -- 原始低效版本 SELECT * FROM user WHERE id NOT IN (48, 49, 51); -- 改良版之一:EXISTS 替代法 SELECT u.* FROM user AS u LEFT JOIN other_table o ON u.id = o.user_id WHERE o.user_id IS NULL; ``` 6. **定期分析统计信息更新频率** 经常检查表元数据的状态变化趋势,并及时刷新内部维护的相关统计数据集,帮助查询规划程序做出更加明智的选择决定. ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值