`
sjk2013
  • 浏览: 2183436 次
文章分类
社区版块
存档分类
最新评论

数据类型不一致导致的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.

分享到:
评论

相关推荐

    经典SQL语句大全

    DB2中列加上后数据类型也不能改变,唯一能改变的是增加varchar类型的长度。 7、说明:添加主键: Alter table tabname add primary key(col) 说明:删除主键: Alter table tabname drop primary key(col) 8、说明...

    SQLServer2008查询性能优化 2/2

    4.8.3 BIT数据类型列上的索引 136 4.8.4 作为一个查询处理的CREATE INDEX语句 136 4.8.5 并行索引创建 136 4.8.6 在线索引创建 137 4.8.7 考虑数据库引擎调整顾问 137 4.9 小结 137 第5章 数据库引擎调整顾问...

    Microsoft SQL Server 2005 Express Edition SP3

    如果在安装完 SQL Server Express 之后更改服务器的角色,便会导致功能丢失,不支持这样做。 [顶部] 3.11 现有的 SQL 本机客户端安装可能导致安装失败 安装可能失败并回滚,同时显示以下错误消息:“找不到产品 ...

    SQLServer2008查询性能优化 1/2

    4.8.3 BIT数据类型列上的索引 136 4.8.4 作为一个查询处理的CREATE INDEX语句 136 4.8.5 并行索引创建 136 4.8.6 在线索引创建 137 4.8.7 考虑数据库引擎调整顾问 137 4.9 小结 137 第5章 数据库引擎调整顾问...

    sql经典语句一部分

    DB2中列加上后数据类型也不能改变,唯一能改变的是增加varchar类型的长度。 7、说明:添加主键: Alter table tabname add primary key(col) 说明:删除主键: Alter table tabname drop primary key(col) 8、说明...

    数据库操作语句大全(sql)

    DB2中列加上后数据类型也不能改变,唯一能改变的是增加varchar类型的长度。 7、说明:添加主键: Alter table tabname add primary key(col) 说明:删除主键: Alter table tabname drop primary key(col) 8、说明...

    聊聊高并发高可用那些事(Kafka、Redis、MySQL)

    - 索引类型和方式、聚簇和非聚簇索引 - 回表、覆盖索引、最左前缀、联合索引、索引下推 - Explain分析SQL语句 - 索引失效的场景、索引优化方案 - TB级数据(600亿条)存储和访问 - 事务特征和隔离级别 - 乐观锁和悲观...

    什么是NoSQL数据库?

    为有数据更新的表做索引或表结构(schema)变更 字段不固定时应用 对简单查询需要快速返回结果的处理 。。。。。。 NoSQL数据库 为了弥补关系型数据库的不足(特别是最近几年),NoSQL数据库出现了。关系型数据库...

    mysql数据库的基本操作语法

    如果需要改变列名建议使用change,如果需要改变数据类型和显示位置可以使用modify 13、 删除表 drop table users; drop删除表会删除表结构,表对象将不存在数据中;数据也不会存在;表内的对象也不存在,如:索引、...

    DbConvertStudioSetup1.7.zip

    该软件能够向用户显示关于数据库类型以及不一致的警告消息,以及关于用户表对象的潜在问题以及处理之前的关系的报告。某些错误可能会导致数据库目标发生冲突,只需轻轻一按对话问题的小型重新配置过程,即可轻松消除...

    数据库资料

    ——信誉值大于5的用户才能够加入会员列表 …… 完整性包括… 实体完整性域完整性引用完整性自定义完整性表操作创建数据库表 SQL Server的数据类型思考创建数据库表思考创建数据库表思考选择主键的原则创建数据库表...

    Windows 系统错误代码简单分析

    可能是一个包含注册表数据文件的结构已损坏,也可能内存中该文件的系统映像已损坏,或者因为备份副本(或日志)不存在(或损坏)导致无法恢复该文件。  1016 由注册表引起的 I/O 操作发生了不可恢复的错误。...

    java面试题,180多页,绝对良心制作,欢迎点评,涵盖各种知识点,排版优美,阅读舒心

    【基础】java基本数据类型(四类八种) 15 Java自动类型转换 16 数据类型自动提升(注意以下讨论的是二元操作符) 16 【基础】switch支持的类型 17 【基础】当一个对象被当作参数传递到一个方法后,此方法可改变这个...

    Mysql高性能优化技能总结

    所有存储相同数据的列名和列类型必须一致(一般作为关联列,如果查询时关联列类型不一致会自动进行数据类型隐式转换,会造成列上的索引失效,导致查询效率降低) 数据库基本设计规范 1. 所有表必须使用Innodb存储...

    。net图书管理系统设计方案

    在可能的情况下,使用较小的数据类型,例如用varchar替代char。 e.考虑使用簇索引来支持排序和范围化查询。在为数据检索优化表时,簇索引必须支持数据的分组索引。为簇关键字选择列或列组,簇关键字以经常需要的顺序...

    XML 讲解和分析

     XML与Access,Oracle和SQL Server等数据库不同,数据库提供了更强有力的数据存储和分析能力,例如:数据索引、排序、查找、相关一致性等,XML仅仅是展示数据。事实上XML与其他数据表现形式最大的不同是:他极其简单...

    易语言程序免安装版下载

    修改外部数据库在4.12版中导致的不兼容问题,并增加了对MS SQL Server数据库中image和text字段类型的说明。 7. 修改扩展界面支持库一,禁止透明标签在父窗口刷新时自动刷新,以解决其导致窗口刷新缓冲的问题。 8....

    MySQL 5.1参考手册

    13.4.2. 不能回滚的语句 13.4.3. 会造成隐式提交的语句 13.4.4. SAVEPOINT和ROLLBACK TO SAVEPOINT语法 13.4.5. LOCK TABLES和UNLOCK TABLES语法 13.4.6. SET TRANSACTION语法 13.4.7. XA事务 13.5. 数据库管理语句 ...

    mysql官方中文参考手册

    13.4.2. 不能回滚的语句 13.4.3. 会造成隐式提交的语句 13.4.4. SAVEPOINT和ROLLBACK TO SAVEPOINT语法 13.4.5. LOCK TABLES和UNLOCK TABLES语法 13.4.6. SET TRANSACTION语法 13.4.7. XA事务 13.5. 数据库管理语句 ...

Global site tag (gtag.js) - Google Analytics