我有一个包含两个索引的表。我一次运行一个插件,每1000行提交一次。我无法进行批量插入,因为业务逻辑需要逐行检查更新的数据。
我的索引导致非常高的db_file_sequential_read等待。我可以命令传入的数据在这个索引上避免这些,但是我在不同的索引上遭受同样的惩罚。
实际的表太长而无法禁用并随后重新创建索引。
这显示了我所遭受的缓慢。第一组数字来自使用加密表空间的登台服务器。第二组数字来自使用非加密表空间的生产服务器。
-- create random test data in foo
create table foo as (
select dbms_random.random() id, dbms_random.string('U', 25) val
from dual connect by level <= 100000
);
create index foo_id_idx on foo (id, val);
-- create data table in bar
create table bar as (
select * from foo where 0 = 1
);
-- populate bar with unordered data (3.12s / 1.22s)
insert into bar select * from foo; commit;
-- add id index
create index bar_id_idx on bar (id);
-- populate indexed bar with unordered data (36.73s / 2.24s)
truncate table bar;
insert into bar select * from foo; commit;
-- populate indexed bar with id ordered data (4.84s / 0.6s)
truncate table bar;
insert into bar select * from foo order by id; commit;
-- add val index (actual production setup)
create index bar_val_idx on bar (val);
-- populate multi-indexed bar with unordered data (84.482s / 3.1s)
truncate table bar;
insert into bar select * from foo order by val; commit;
-- populate multi-indexed bar with id ordered data (50.641s / 2.631s)
truncate table bar;
insert into bar select * from foo order by id; commit;
-- alter index on foo to support order by clause
drop index foo_id_idx;
create index foo_val_idx on foo (val, id);
-- populate multi-indexed bar with val ordered data (37.31s / 2.66s)
truncate table bar;
insert into bar select * from foo order by val; commit;
这似乎是第二个指数从5s到84s的巨大惩罚。当然,我可以通过排序数据来绕过一个索引的大部分惩罚,但两者都不能。我应该查看缓冲区,缓存,内存或其他东西以帮助避免磁盘IO,还是应该查看其他一些策略,如索引组织表?
编辑1:从生产箱中添加数字&amp;等待信息。
在使用实际插入过程进行生产的一小时内(不是上面的简化示例): 处决56,715 行处理56,715 解析1 磁盘读取36,958 排序0 缓冲区获得754,970 db_file_sequential_read等待323s 内存/ CPU等待26s
答案 0 :(得分:0)
如果您存储两份副本,则可能会以两个不同的顺序存储相同的数据:
这可以批量更新,从而为自己的维护提供一些利润。保持手指交叉,以便高级查询重写正常工作。
答案 1 :(得分:0)
mview的可执行示例。 如果且仅当第二个索引的逐行插入成为问题时,由于在提交时批量更新mview,这很难执行得更快。
set timing on
create table foo (
id number,
val varchar2(30)
) pctfree 0;
create index foo_id_idx on foo (id, val);
alter table foo
add constraint pk_foo primary key (id) using index foo_id_idx;
create materialized view log on foo with primary key;
create table mv_foo (
id number,
val varchar2(30),
constraint pk_mv_foo primary key (val, id)
) organization index;
create materialized view mv_foo
on prebuilt table
refresh fast on commit with primary key
enable query rewrite
as
select id, val
from foo;
begin
-- to reset mview staleness
dbms_mview.refresh('mv_foo', method => 'c');
end;
/
insert into foo(id, val)
select dbms_random.random(), dbms_random.string('U', 25)
from dual connect by level <= 10000;
commit;
begin
dbms_stats.gather_table_stats(user, 'foo');
dbms_stats.gather_table_stats(user, 'mv_foo');
end;
/
explain plan for
select /*+ first rows */
id, val
from foo
order by id, val;
select * from table(dbms_xplan.display);
explain plan for
select /*+ first rows */
id, val
from foo
order by val, id;
select * from table(dbms_xplan.display);
请参阅第二个声明中按VAL过滤FOO时透明使用mview IOT:
explain plan for select * from foo where id = :x
explain plan succeeded.
6ms elapsed
select * from table(dbms_xplan.display)
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------
Plan hash value: 2466643623
-------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 33 | 2 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN| FOO_ID_IDX | 1 | 33 | 2 (0)| 00:00:01 |
-------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("ID"=TO_NUMBER(:Z))
explain plan for select * from foo where val = :x
explain plan succeeded.
25ms elapsed
select * from table(dbms_xplan.display)
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------
Plan hash value: 386525678
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 33 | 2 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN| PK_MV_FOO | 1 | 33 | 2 (0)| 00:00:01 |
------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("MV_FOO"."VAL"=:X)
您需要QUERY REWRITE系统权限才能正常工作。