我有一個包含兩個索引的表。我每次運行一個插入,每1000行提交一次。我無法進行批量插入,因爲業務邏輯需要逐行檢查更新的數據。如何在插入期間避免索引上的db_file_sequential_read
我的索引造成非常高的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;
對於第二個索引從5秒到84秒這似乎是一個巨大的懲罰。當然,我可以通過訂購數據來繞過一個索引的大部分處罰,但不能同時處理兩者。我是否應該查看緩衝區,緩存,內存或其他內容以幫助避免磁盤IO,還是應該查看其他策略,如索引組織表?
編輯1:從生產箱中添加數字&等待信息。
在生產與實際的插入處理(不高於簡化例子)1小時: 處決56715個 行耗時56715名 解析1 磁盤讀取36958個 排序0 緩衝區獲取754970 db_file_sequential_read等待323S 存儲器/ CPU等待26S
您正在運行的機器的規格是什麼?這些時間看起來非常緩慢。其他一些事情。一世。每行需要完成的處理是什麼?你確定*這不能作爲公牛插入的一部分嗎? II。你確定等待事件來自索引維護嗎? III。你的桌子的大小是多少,無論是在行和GB – BobC
@Aaron,我同意BobC你的運行時間似乎很慢。我在臺式電腦上運行了整個腳本,所有時間都比我的速度慢了10倍以上。在擔心數據結構之前,您可能需要查看操作系統,硬件,SAN等。或者查看一些AWR數據以查看數據庫的性能,例如:select * from dba_hist_sysmetric_history 其中metric_name ='平均同步單塊讀取延遲';'。 –
@BobC這是一個臨時服務器,其規格遠遠低於生產服務器,但配置完全相同,並且使用相同的NAS。我也意識到我正在爲表和索引使用加密的表空間。這就是說 - 我更關心這個例子中表現的相對差異。我將生產服務器中的數字添加到未加密的表空間中,直到原始問題。如果你仍然認爲表現不佳,那麼我會好奇進一步調查。 – Aaron