现在只用一行查询前大表的奇怪行为

时间:2015-05-19 11:19:01

标签: sql oracle oracle11g

我在测试环境中有一个非常简单的表。昨天它有约。一百万条目。我删除了它们(delete from mytable; commit;)。实际上它有1个单行。

我不明白(每次选择多次测试以获得执行时间):

select * from myTable; --took 30 to 40 secs first, now constantly  9 secs
select count(*) from myTable; -- returns 1, takes  9 secs
select * from myTable where rownum < 2; --returns my single row, takes 30 millisecs
select * from tm_global_error where rownum < 3; -- returns my single row, takes  9 secs

为什么全表扫描需要这么长时间?为什么Oracle没有意识到,只有一行?

analyze table myTable COMPUTE STATISTICS;analyze table myTable COMPUTE STATISTICS for all indexed columns;都没有做任何改变。

版本:Oracle Database 11g企业版11.2.0.3.0版 - 64位

执行计划:

select * from myTable;

-------------------------------------------------------------------------------------
| Id  | Operation         | Name            | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |                 |     1 |  2115 | 50921   (1)| 00:10:12 |
|   1 |  TABLE ACCESS FULL| myTable         |     1 |  2115 | 50921   (1)| 00:10:12 |
-------------------------------------------------------------------------------------

select count(*) from myTable;

------------------------------------------------------------------------------
| Id  | Operation          | Name            | Rows  | Cost (%CPU)| Time     |
------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |                 |     1 | 50921   (1)| 00:10:12 |
|   1 |  SORT AGGREGATE    |                 |     1 |            |          |
|   2 |   TABLE ACCESS FULL| myTable         |     1 | 50921   (1)| 00:10:12 |
------------------------------------------------------------------------------


select * from myTable where rownum < 2;

--------------------------------------------------------------------------------------
| Id  | Operation          | Name            | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |                 |     1 |  2115 | 50921   (1)| 00:10:12 |
|*  1 |  COUNT STOPKEY     |                 |       |       |            |          |
|   2 |   TABLE ACCESS FULL| myTable         |     1 |  2115 | 50921   (1)| 00:10:12 |
--------------------------------------------------------------------------------------

select * from myTable where rownum < 3;

--------------------------------------------------------------------------------------
| Id  | Operation          | Name            | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |                 |     1 |  2115 | 50921   (1)| 00:10:12 |
|*  1 |  COUNT STOPKEY     |                 |       |       |            |          |
|   2 |   TABLE ACCESS FULL| myTable         |     1 |  2115 | 50921   (1)| 00:10:12 |
--------------------------------------------------------------------------------------

DDL:

CREATE TABLE mytable
(
  ID         NUMBER,
  field1     VARCHAR2(255 CHAR),
  field2     VARCHAR2(255 CHAR),
  field3     VARCHAR2(255 CHAR),
  field3     VARCHAR2(255 CHAR),
  field4     VARCHAR2(255 CHAR),
  field5     NUMBER,
  field6     TIMESTAMP(6),
  field7     NUMBER,
  field8     VARCHAR2(255 CHAR),
  field9     VARCHAR2(1 CHAR)                DEFAULT 'N',
  field10    VARCHAR2(255 CHAR),
  field11    CLOB,
  field12    DATE,
  field13    VARCHAR2(500 CHAR),
  field14    VARCHAR2(10 CHAR),
  field15    DATE
)
LOB (field11) STORE AS (
  TABLESPACE  myTS
  ENABLE      STORAGE IN ROW
  CHUNK       8192
  RETENTION
  NOCACHE
  LOGGING
      STORAGE    (
                  INITIAL          64K
                  NEXT             1M
                  MINEXTENTS       1
                  MAXEXTENTS       UNLIMITED
                  PCTINCREASE      0
                  BUFFER_POOL      DEFAULT
                  FLASH_CACHE      DEFAULT
                  CELL_FLASH_CACHE DEFAULT
                 ))
TABLESPACE myTS
RESULT_CACHE (MODE DEFAULT)
PCTUSED    0
PCTFREE    10
INITRANS   1
MAXTRANS   255
STORAGE    (
            INITIAL          64K
            NEXT             1M
            MAXSIZE          UNLIMITED
            MINEXTENTS       1
            MAXEXTENTS       UNLIMITED
            PCTINCREASE      0
            BUFFER_POOL      DEFAULT
            FLASH_CACHE      DEFAULT
            CELL_FLASH_CACHE DEFAULT
           )
LOGGING 
NOCOMPRESS 
NOCACHE
NOPARALLEL
MONITORING;


CREATE UNIQUE INDEX my_IDX ON mytable
(ID)
LOGGING
TABLESPACE myTS
PCTFREE    10
INITRANS   2
MAXTRANS   255
STORAGE    (
            INITIAL          64K
            NEXT             1M
            MAXSIZE          UNLIMITED
            MINEXTENTS       1
            MAXEXTENTS       UNLIMITED
            PCTINCREASE      0
            BUFFER_POOL      DEFAULT
            FLASH_CACHE      DEFAULT
            CELL_FLASH_CACHE DEFAULT
           )
NOPARALLEL;


CREATE OR REPLACE TRIGGER myTable_IT
BEFORE INSERT OR UPDATE
ON myTable
REFERENCING NEW AS New OLD AS Old
FOR EACH ROW
BEGIN
:new.field12 := sysdate;
END;
/


ALTER TABLE myTable ADD (
  CONSTRAINT my_const
  CHECK (field9 in ('Y','N'))
  ENABLE VALIDATE);

2 个答案:

答案 0 :(得分:2)

表空间仍然存在,你必须缩小它。我曾经遇到过同样的问题。我在这里找到了解决方案:Slow query execution in an empty table. (after deleting a large amount of inserts)

简而言之:

alter table xyz shrink space

答案 1 :(得分:2)

使用其中一种(取决于Oracle版本):

  • alter table t shrink space compact;

  • alter table t move;
  • 每个表索引
  • alter index t_ix* rebuild;

CTAS的另一个选择(创建表格为选择):

  • create table t1 as select * from t;
  • drop table t;
  • alter table t1 rename to t;
  • 再次在新表T;
  • 上重新创建所有索引

所有操作(shrink space除外)都处于脱机状态。