[20151228]小表全表扫描为何如此慢2.txt

[20151228]小表全表扫描为何如此慢2.txt

--论坛上有人问的问题,小表全表扫描为何如此慢,200M的大小。链接如下。
http://www.itpub.net/thread-2049088-1-1.html

--我的猜测是可能含有lob字段,不过对方的恢复没有lob字段。仔细检查发现array使用缺省值,zergduan,bfc99观察都比我细致。

--拿例子sh.sales测试看看。
SCOTT@book> @ &r/ver1
PORT_STRING                    VERSION        BANNER
------------------------------ -------------- --------------------------------------------------------------------------------
x86_64/Linux 2.4.xx            11.2.0.4.0     Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

SCOTT@book> show array
arraysize 15

SCOTT@book> set autot traceonly
SCOTT@book> set timing on
SCOTT@book> select * from sh.sales;
918843 rows selected.

Elapsed: 00:00:19.60

Execution Plan
----------------------------------------------------------
Plan hash value: 1550251865
---------------------------------------------------------------------------------------------
| Id  | Operation           | Name  | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
---------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |       |   918K|    25M|   525   (2)| 00:00:07 |       |       |
|   1 |  PARTITION RANGE ALL|       |   918K|    25M|   525   (2)| 00:00:07 |     1 |    28 |
|   2 |   TABLE ACCESS FULL | SALES |   918K|    25M|   525   (2)| 00:00:07 |     1 |    28 |
---------------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
      62795  consistent gets
       1625  physical reads
          0  redo size
   36919530  bytes sent via SQL*Net to client
     674335  bytes received via SQL*Net from client
      61258  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
     918843  rows processed

--表大小25M,需要19秒。

SCOTT@book> set array 200
SCOTT@book> select * from sh.sales;
918843 rows selected.
Elapsed: 00:00:12.59
Execution Plan
----------------------------------------------------------
Plan hash value: 1550251865
---------------------------------------------------------------------------------------------
| Id  | Operation           | Name  | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
---------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |       |   918K|    25M|   525   (2)| 00:00:07 |       |       |
|   1 |  PARTITION RANGE ALL|       |   918K|    25M|   525   (2)| 00:00:07 |     1 |    28 |
|   2 |   TABLE ACCESS FULL | SALES |   918K|    25M|   525   (2)| 00:00:07 |     1 |    28 |
---------------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
       6218  consistent gets
       1619  physical reads
          0  redo size
   26550384  bytes sent via SQL*Net to client
      51053  bytes received via SQL*Net from client
       4596  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
     918843  rows processed

--设置array=200, 需要13秒,快了50%。行记录918843/网络往返4596=199.9223237597911227154,基本吻合。
--再来看看包含lob字段的情况:

SCOTT@book> create table t (id number,text clob ) ;
Table created.

SCOTT@book> insert into t select rownum ,lpad('a',40,'a') from dual connect by level <=1e4;
10000 rows created.

SCOTT@book> commit ;
Commit complete.

SCOTT@book> set array 2
SCOTT@book> select id from t ;

SCOTT@book> show array
arraysize 200
SCOTT@book> set autot traceonly
SCOTT@book> set timing on
SCOTT@book> select * from t;
10000 rows selected.
Elapsed: 00:04:51.68
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      | 10000 |  1826K|    68   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| T    | 10000 |  1826K|    68   (0)| 00:00:01 |
--------------------------------------------------------------------------
Statistics
----------------------------------------------------------
         14  recursive calls
          0  db block gets
      10031  consistent gets
          0  physical reads
          0  redo size
   11160334  bytes sent via SQL*Net to client
    7170519  bytes received via SQL*Net from client
      30002  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      10000  rows processed

--改用to_char函数。
SCOTT@book> select id,to_char(text) from t ;
10000 rows selected.
Elapsed: 00:00:00.14
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      | 10000 |  1826K|    68   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| T    | 10000 |  1826K|    68   (0)| 00:00:01 |
--------------------------------------------------------------------------
Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
        239  consistent gets
          0  physical reads
          0  redo size
      99483  bytes sent via SQL*Net to client
       1058  bytes received via SQL*Net from client
         51  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      10000  rows processed

--很明显第2次快许多。仔细检查网络往返就很容易明白问题所在。
--第2次51次很好解读,10000条记录,array=200, 相等于50次就可以完成,51次基本复合测试结果。换1句话讲,当使用to_char函数时
--oracle是先"打包好"数据在上传的。

--而当存在lob字段时,出现30002次往返,我估计oracle是1条记录1条记录的上传,每条记录3个往返,导致整个效率低下。

--测试取1条与2条记录就可以看出问题:

SCOTT@book> select * from t where rownum<=1;
Elapsed: 00:00:00.06
Execution Plan
----------------------------------------------------------
Plan hash value: 508354683
---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |   187 |     2   (0)| 00:00:01 |
|*  1 |  COUNT STOPKEY     |      |       |       |            |          |
|   2 |   TABLE ACCESS FULL| T    |     1 |   187 |     2   (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(ROWNUM<=1)

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

SCOTT@book> select * from t where rownum<=2;
Elapsed: 00:00:00.10
Execution Plan
----------------------------------------------------------
Plan hash value: 508354683
---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     2 |   374 |     2   (0)| 00:00:01 |
|*  1 |  COUNT STOPKEY     |      |       |       |            |          |
|   2 |   TABLE ACCESS FULL| T    |     2 |   374 |     2   (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(ROWNUM<=2)
Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          4  consistent gets
          0  physical reads
          0  redo size
       2764  bytes sent via SQL*Net to client
       1953  bytes received via SQL*Net from client
          8  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          2  rows processed

-- SQL*Net roundtrips to/from client =5,8 也说明取1条记录需要3次网络往返,逻辑读仅仅增加1次。
-- 另外oracle传输数据实际是压缩的。
-- 如果使用to_char函数
--99483/50/200=9.9483,平均每条记录仅仅10个字节,比实际小许多,也说明数据是压缩传送的。

-- 如果不使用to_char函数
--11160334/30002=371.9863342443837775281

--真不知道平均每次为什么这么多。估计考虑网络协议的开销,真正的数据并没有占多少。

时间: 2024-09-07 15:01:46

[20151228]小表全表扫描为何如此慢2.txt的相关文章

[20151222]小表全表扫描为何如此慢.txt

[20151222]小表全表扫描为何如此慢.txt --论坛上有人问的问题,小表全表扫描为何如此慢,200M的大小.链接如下. http://www.itpub.net/thread-2049088-1-1.html --我的猜测是可能含有lob字段.自己测试看看: 1.环境: SCOTT@book> @ &r/ver1 PORT_STRING                    VERSION        BANNER ------------------------------ --

SELECT INTO 语句数据表全表复制备份

select into 语句数据表全表复制备份 select into 语句常用于创建表的备份复件或者用于对记录进行存档. sql select into 语法 您可以把所有的列插入新表: select * into new_table_name [in externaldatabase] from old_tablename 或者只把希望的列插入新表: select column_name(s) into new_table_name [in externaldatabase] from ol

ORACLE SQL调优之记录一次trim函数引发的大表全表扫描

                                                                                                                                       

浅析Oracle全表扫描下的逻辑读

T1表全表扫描产生逻辑读的分析 做个实验给你演示一下:以表t1为例,对段t1做dump 1.t1表就一条数据 gyj@OCM> select * from t1;      ID NAME ---------- ----------       1 AAAAA 2.找t1段的段头块 gyj@OCM> select  header_file,header_block from dba_segments where segment_name='T1' and owner='GYJ'; HEADER

库表字符集不一致导致的全表扫描问题

背景: 当数据库的建库字符集和表不一样时,在库下针对表创建存储过程可能导致全表扫描 如下例: drop database if exists xx1; drop database if exists xx2; create database xx1 character set utf8; create database xx2 character set gbk;   然后分别在xx1 和 xx2下执行: CREATE TABLE t1 ( `col1` varchar(10) NOT NULL

SQL SERVER中关于OR会导致索引扫描或全表扫描的浅析

在SQL SERVER的查询语句中使用OR是否会导致不走索引查找(Index Seek)或索引失效(堆表走全表扫描 (Table Scan).聚集索引表走聚集索引扫描(Clustered Index Scan))呢?是否所有情况都是如此?又该如何优化呢? 下面我们通过一些简单的例子来分析理解这些现象.下面的实验环境为SQL SERVER 2008,如果在不同版本有所区别,欢迎指正.   堆表单索引 首先我们构建我们测试需要实验环境,具体情况如下所示: DROP TABLE TEST    CRE

大幅提升MySQL中InnoDB的全表扫描速度的方法_Mysql

 在 InnoDB中更加快速的全表扫描 一般来讲,大多数应用查询的时候都会用索引,查找很少的几行数据(主键查找或百行内的查询),但有时候我们需要全表查询.典型的全表扫描就是逻辑备份  (mysqldump) 和 online schema changes( 注:在线上对大表 schema 的操作,也是 facebook 的一个开源项目) (SELECT ... INTO OUTFILE).  在 Facebook我们用 mysqldump 来备份数据库. 正如你所知MySql提供两种备份方式,提

Oracle 全表扫描及其执行计划(full table scan)

    全表扫描是Oracle访问数据库表是较为常见的访问方式之一.很多朋友一看到SQL语句执行计划中的全表扫描,就要考虑对其进行修理一番.全表扫描的存在,的确存在可能优化的余地.但事实上很多时候全表扫描也并非是最低效的,完全要看不同的情形与场合,任一方式都是有利有弊的,也就是具体情况要具体分析.本文描述了什么是全表扫描以及何时发生全表扫描,何时全表扫描才低效.  本文涉及到的相关链接:     高水位线和全表扫描      启用 AUTOTRACE 功能     Oracle 测试常用表BIG

并行方式全表扫描功能已提交 PG 9.6 版主干代码

我以前建议过将并行全表扫描功能加入至PostgreSQL 9.5中,但未实现.然而,今天我很高兴地向各位通报 我已经将第一版本的并行扫描功能提交至PostgreSQL的开发主分支中,我们确认它将会包含在将要发布的9.6版本中. 为PostgreSQL增加并行查询功能,目前这只是第一步,它也是我长久以来的一个梦想,我已为此工作了好几年了, 最早真正开发时是在9.4版本的开发期间,那时我主要是开发了一些后台动态进程和动态共享内存:接着在9.5版本 期间,我又增加了很多有关并行机制的底层基本加松的开发