我在测试环境中有一个非常简单的表。昨天它有约。一百万条目。我删除了它们(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);
答案 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
除外)都处于脱机状态。