数据类型不一致导致的SQL不走索引

前几天,同事发来一条SQL,说是更新操作的时候执行的很慢,我看了下,数据量也不是很大。再查看执行计划,发现是执行路径错误导致的,可是为什么会走错误的执行路径呢?统计信息并没有太大的问题。在这里模拟下:

数据准备:

--1.数据准备,表一:
DROP TABLE t_test_1;
create table T_TEST_1
(
  owner          VARCHAR2(30),
  object_name    VARCHAR2(128),
  subobject_name VARCHAR2(30),
  object_id      NUMBER,
  data_object_id NUMBER,
  object_type    VARCHAR2(19),
  created        DATE,
  last_ddl_time  DATE,
  timestamp      VARCHAR2(19),
  status         VARCHAR2(7),
  temporary      VARCHAR2(1),
  generated      VARCHAR2(1),
  secondary      VARCHAR2(1)
);
INSERT INTO T_TEST_1
SELECT * FROM dba_objects;
COMMIT;
UPDATE t_test_1 a SET a.object_type = 'TABLE';
COMMIT;
--2.数据准备,表二:
DROP TABLE t_test_2;
create table T_TEST_2
(
  owner          VARCHAR2(30),
  object_name    VARCHAR2(128),
  subobject_name VARCHAR2(30),
  --这里数据类型和T_TEST_1中object_id的数据类型不一致
  object_id      VARCHAR2(100),
  data_object_id NUMBER,
  object_type    VARCHAR2(19),
  created        DATE,
  last_ddl_time  DATE,
  timestamp      VARCHAR2(19),
  status         VARCHAR2(7),
  temporary      VARCHAR2(1),
  generated      VARCHAR2(1),
  secondary      VARCHAR2(1),
  --这里数据类型和T_TEST_1中object_id的数据类型一致
  object_id2      NUMBER
);
INSERT INTO T_TEST_2
SELECT a.*, a.object_id object_id2 FROM dba_objects a;
COMMIT;
SELECT * FROM t_test_1;
CREATE INDEX ind_t_test_2_id1 ON t_test_2(object_id) TABLESPACE TBS_LUBINSU_DATA;
CREATE INDEX ind_t_test_2_id2 ON t_test_2(object_id2) TABLESPACE TBS_LUBINSU_DATA;

T_TEST_2表中的object_id和object_id2两个字段都创建了索引

在这里需要更新表1的对象类型字段object_type:

--更新数据
UPDATE t_test_1 a
SET    a.object_type =
       (SELECT i.object_type FROM t_test_2 i WHERE i.object_id = a.object_id);

UPDATE t_test_1 a
SET    a.object_type =
       (SELECT i.object_type FROM t_test_2 i WHERE i.object_id2 = a.object_id);

第一条SQL中T_TEST_2的object_id和T_TEST_1中的object_id数据类型是不一致的,而第二条中两个字段数据类型是一致的。

我们来看下执行计划:

SQL> EXPLAIN PLAN FOR
  2  UPDATE t_test_1 a
  3  SET    a.object_type =
  4         (SELECT i.object_type FROM t_test_2 i WHERE i.object_id = a.object_id);
 
Explained
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2933162137
-------------------------------------------------------------------------------
| Id  | Operation          | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------
|   0 | UPDATE STATEMENT   |          | 64296 |  1506K|   137   (3)| 00:00:02 |
|   1 |  UPDATE            | T_TEST_1 |       |       |            |          |
|   2 |   TABLE ACCESS FULL| T_TEST_1 | 64296 |  1506K|   137   (3)| 00:00:02 |
|*  3 |   TABLE ACCESS FULL| T_TEST_2 |   603 | 37989 |   150   (3)| 00:00:02 |
-------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   3 - filter(TO_NUMBER("I"."OBJECT_ID")=:B1)
Note
-----
   - dynamic sampling used for this statement
 
19 rows selected

我们可以看到,在这里Oracle对两个表都执行了全表扫描。

下面再看另外一句:

[lubinsu@localhost ~]$ sqlplus lubinsu/lubinsu

SQL*Plus: Release 10.2.0.1.0 - Production on Sat May 25 12:06:14 2013

Copyright (c) 1982, 2005, Oracle.  All rights reserved.


Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options

SQL> set timing on
SQL> set autotrace traceonly
SQL> UPDATE t_test_1 a
  2  SET    a.object_type =
  3         (SELECT i.object_type FROM t_test_2 i WHERE i.object_id2 = a.object_id);

49894 rows updated.

Elapsed: 00:00:02.41

Execution Plan
----------------------------------------------------------
Plan hash value: 2786494037

--------------------------------------------------------------------------------
-----------------

| Id  | Operation                    | Name             | Rows  | Bytes | Cost (
%CPU)| Time     |

--------------------------------------------------------------------------------
-----------------

|   0 | UPDATE STATEMENT             |                  | 64296 |  1506K|   137
  (3)| 00:00:02 |

|   1 |  UPDATE                      | T_TEST_1         |       |       |
     |          |

|   2 |   TABLE ACCESS FULL          | T_TEST_1         | 64296 |  1506K|   137
  (3)| 00:00:02 |

|   3 |   TABLE ACCESS BY INDEX ROWID| T_TEST_2         |   603 | 14472 |     6
  (0)| 00:00:01 |

|*  4 |    INDEX RANGE SCAN          | IND_T_TEST_2_ID2 |   241 |       |     1
  (0)| 00:00:01 |

--------------------------------------------------------------------------------
-----------------


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

   4 - access("I"."OBJECT_ID2"=:B1)

Note
-----
   - dynamic sampling used for this statement


Statistics
----------------------------------------------------------
        448  recursive calls
     101974  db block gets
     100838  consistent gets
        110  physical reads
   23668060  redo size
        668  bytes sent via SQL*Net to client
        658  bytes received via SQL*Net from client
          4  SQL*Net roundtrips to/from client
         11  sorts (memory)
          0  sorts (disk)
      49894  rows processed

--排版不好,整理下:
SQL> set linesize 200
SQL> /

49894 rows updated.

Elapsed: 00:00:03.98

Execution Plan
----------------------------------------------------------
Plan hash value: 2786494037

-------------------------------------------------------------------------------------------------
| Id  | Operation                    | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------------
|   0 | UPDATE STATEMENT             |                  | 64296 |  1506K|   137   (3)| 00:00:02 |
|   1 |  UPDATE                      | T_TEST_1         |       |       |            |          |
|   2 |   TABLE ACCESS FULL          | T_TEST_1         | 64296 |  1506K|   137   (3)| 00:00:02 |
|   3 |   TABLE ACCESS BY INDEX ROWID| T_TEST_2         |   603 | 14472 |     6   (0)| 00:00:01 |
|*  4 |    INDEX RANGE SCAN          | IND_T_TEST_2_ID2 |   241 |       |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------

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

   4 - access("I"."OBJECT_ID2"=:B1)

Note
-----
   - dynamic sampling used for this statement


Statistics
----------------------------------------------------------
        326  recursive calls
     101033  db block gets
     100815  consistent gets
          0  physical reads
   12975952  redo size
        676  bytes sent via SQL*Net to client
        658  bytes received via SQL*Net from client
          4  SQL*Net roundtrips to/from client
         11  sorts (memory)
          0  sorts (disk)
      49894  rows processed

SQL> 
可见这里,是走了索引的。END-lubinsu.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
SQL 中使用 LIKE 操作符进行模糊匹配时,如果没有正确使用索引,可能会导致索引失效,从而影响查询性能。以下是一些可能导致 LIKE 索引失效的情况: 1. 前导通配符:如果 LIKE 表达式以通配符 '%' 开头,索引将无法有效利用。例如,"WHERE column LIKE '%abc'",这种情况下索引将无法生效。 2. 不适当的通配符位置:如果 LIKE 表达式中的通配符位于开头和结尾之间,而不是结尾之后,索引的效果可能会减弱。例如,"WHERE column LIKE 'abc%def'",索引可能无法完全匹配。 3. 多个通配符:如果 LIKE 表达式中包含多个通配符,如 '%' 或 '_',索引可能无法生效。例如,"WHERE column LIKE '%abc%def%'",这种情况下索引可能无法使用。 4. 字符集问题:如果列的字符集与 LIKE 表达式中的字符集不匹配,索引可能无法使用。确保字符集一致可以提高索引的效果。 5. 数据类型问题:如果列的数据类型与 LIKE 表达式中的数据类型不匹配,索引可能无法使用。确保数据类型一致可以提高索引的效果。 为了让 LIKE 操作符在查询中有效利用索引,可以考虑以下方法: - 尽量避免在 LIKE 表达式的开头使用通配符。 - 使用索引友好的通配符位置,将通配符放在结尾之后。 - 避免使用多个通配符。 - 确保字符集和数据类型一致。 如果以上方法无法解决问题,可以考虑其他技术手段,如全文搜索引擎或者使用其他类型索引(如全文索引),以满足模糊查询的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值