2013-05-17 60 views
1

有一個表Ta柱:資源忙而重建索引

CREATE TABLE T { 
    id_t integer not null, 
    text varchar2(100), 
    a integer 
} 
/

ALTER TABLE T ADD CONSTRAINT PK_T PRIMARY KEY (ID_T) 
/

指數創建這樣的:

CREATE INDEX IDX_T$A ON T(a); 

也有這樣一個檢查約束:

ALTER TABLE T ADD CONSTRAINT CHECK (a is null or a = 1); 

T中的大部分記錄的空值爲a,因此如果索引處於一致狀態並且其統計數據是最新的,則使用該索引的查詢將非常快速地工作。

但問題是某些行的值a真的很頻繁地改變(一些行得到空值,一些得到1),我需要重建索引讓我們說每小時。

然而,真正經常在工作時這樣做,試圖重建索引,它得到一個例外:

ORA-00054: resource busy and acquire with NOWAIT specified 

任何人可以幫助我這個問題的應對?

+1

你可以用重試機制來處理它。捕獲資源繁忙異常並再次嘗試,直到成功。 –

+0

快速變化對您的索引有什麼影響,導致需要進行這些頻繁重建? –

+0

統計數據過期非常快。重新編譯會統計數據並使索引更小(讀取查詢會變得更快)。 – ZZa

回答

1

大多數情況下不需要重建索引。當然,新創建的索引是高效的,它們的效率隨着時間的推移而下降但是這個過程會在一段時間後停止 - 它只是收斂到一定的水平。

如果您確實需要優化索引,請嘗試使用侵入性較小的DDL命令「ALTER INDEX SHRINK SPACE COMPACT」。 PS:我還建議你爲你的表空間存儲使用一些較小的塊大小(4K或8K)。

+0

想象一下,在表格中有數百萬行且只有其中一百個沒有索引列的空值,一個小時後非空值有絕對不同的行(先前的列中有空值),您確定索引不會持續增長並且效率越來越低嗎? – ZZa

+0

Oracle索引是自我整理。至少在某種程度上。它也取決於列索引的順序。如果索引不適合您的搜索需求,請查找「星型設計模式」 - 用於數據倉庫系統。這很簡單。或者也可以選擇「壓縮」索引。 – ibre5041

+0

還有一條評論,索引「大小」可以用不同的度量來表示。段大小 - 索引佔用多少字節。葉塊數量 - 葉塊數量有多少。他們每個人都有自己的意思。 (順便說一下:索引由分支塊,葉塊和空閒塊組成) – ibre5041

1

您是否嘗試將「ONLINE」添加到該索引重建語句中?

編輯:如果在網上重建不可用,那麼你可以看看上犯了快速刷新的物化視圖存儲ROWID的或行的主鍵,對於A列有1

開始帶看文檔: -

http://docs.oracle.com/cd/B28359_01/server.111/b28326/repmview.htm http://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_6002.htm#SQLRF01302

你會在表上創建物化視圖日誌,然後一個物化視圖。

特別想到這樣的資源需求:對主表的更改需要將更改向量寫入物化視圖日誌,這實際上是每次更改的附加插入。然後,更改必須傳播到另一個表(物化視圖存儲表),並附加查詢。這絕不是一個低影響的選擇。

+0

重建在線是企業選項,不適用於我。 – ZZa

+0

你能提供一個你對mate化視圖意味着什麼的例子嗎?它看起來非常好。 – ZZa

0

由於該字段的基數很低,我建議使用位圖索引並完全跳過重建。

CREATE BITMAP INDEX IDX_T$A ON T(a); 

注(如在評論中提到):事務性能是位圖索引非常低,因此,如果有做更新表中很少有重疊的交易,這將只是很好地工作。

+0

但是,如果這些值在多個會話中快速變化,那麼對於併發而言,這將會非常糟糕。 –

+2

這是[絕對不推薦](http://www.oracle.com/technetwork/articles/sharma-indexes-093638.html)使用位圖索引,如果數據同時由多個進程同時更改並且頻繁地更改。 – ZZa

+0

順便說一下'select * from v $ option其中parameter ='Bit-mapped indexes''表示它在standart版本中也不可用。 – ZZa

1

重建績效

大多數Oracle專家對此表示懷疑經常重建索引。例如,快速瀏覽演示文稿Rebuilding the Truth會告訴你,索引不會以許多人認爲他們所做的天真方式行事。

該演示文稿中的一個相關要點是「完全刪除的塊被回收並且通常不成問題」。如果你的價值完​​全改變,那麼你的指數不應該變得無限大。雖然您的索引以非典型方式使用,但這種行爲可能是一件好事。

下面是一個簡單的例子。創建100萬行並將其索引爲100。

--Create table, constraints, and index. 
CREATE TABLE T 
(
    id_t integer primary key, 
    text varchar2(100), 
    a integer check (a is null or a = 1) 
); 

CREATE INDEX IDX_T$A ON T(a); 

--Insert 1M rows, with 100 "1"s. 
insert into t 
select level, level, case when mod(level, 10000) = 0 then 1 else null end 
from dual connect by level <= 1000000; 
commit; 

--Initial sizes: 
select segment_name, bytes/1024/1024 MB 
from dba_segments 
where segment_name in ('T', 'IDX_T$A'); 

SEGMENT_NAME MB 
T    19 
IDX_T$A   0.0625 

現在完全洗牌索引行大約1000次。

--Move the 1s around 1000 times. Takes about 6 minutes. 
begin 
    for i in 9000 .. 10000 loop 
     update t 
     set a = case when mod(id_t, i) = 0 then 1 else null end 
     --Don't update if the vlaue is the same 
     where nvl(a,-1) <> nvl(case when mod(id_t,i) = 0 then 1 else null end,-1); 
     commit; 
    end loop; 
end; 
/

索引段大小仍然相同。

--The the index size is the same. 
select segment_name, bytes/1024/1024 MB 
from dba_segments 
where segment_name in ('T', 'IDX_T$A'); 

SEGMENT_NAME MB 
T    19 
IDX_T$A   0.0625 

重建統計

這是很好的擔心對象,其數據變化如此顯着的統計信息。但是,同樣,儘管你的系統不常見,但在默認的Oracle行爲下它可能正常工作。雖然索引的行可能完全改變,但相關的統計數據可能保持不變。如果總是有100行索引,則行數,塊數和獨特性將保持不變。

如果100行從完全隨機變爲彼此非常接近,也許聚類因子會發生顯着變化。但即使這可能並不重要。如果有數百萬行,但只有100個索引,那麼優化程序的決定可能是相同的,無論聚類因子如何。讀取1個塊(令人敬畏的聚類因子)或讀取100個塊(最壞情況聚類因子)仍然比完成數百萬行的全表掃描要好得多。

但統計很複雜,我肯定是過分簡化了事情。如果您需要以特定方式保留統計信息,則可能需要鎖定它們。不幸的是,你不能只鎖定一個索引,但你可以鎖定表和它的依賴索引。

begin 
    dbms_stats.lock_table_stats(ownname => user, tabname => 'T'); 
end; 
/

重建反正

如果重建仍然是必要的,@Robe Eleckers想法重新嘗試應該工作。雖然不是例外,但設置DDL_LOCK_TIMEOUT會更容易。

alter session set ddl_lock_timeout = 500; 

該會話仍然需要在表格上獲得排他鎖定,但這樣會更容易找到合適的機會窗口。

+0

你的答案非常有用!這是一個偉大的工作! – ZZa