Using Oracle Blocks Efficiently
1、DB的存儲層次(在其他文章中已經介紹過了,這里只是簡述)
1)blocks:是data file I/O的最小單位,也是空間分配的最小單位。一個Oracle block是由一個或多個連續的OS blocks組成。
2)extents:是由多個連續的data blocks組成的擁有存儲空間分配的邏輯單位。一個或多個extents組成了一個segment。當在一個segment中的所有空間都被用完時,Oracle server會給segment分配新的extent。
3)segments:一個segment是一個extents的集合,存放了tablespace中具體的邏輯存儲結構的所有數據。例如,每個 table,Oracle server會分配一個或多個extents用于組成該table的data segments。對于indexes,Oracle server分配一個或多個extents用于組成index segment。
2、extents的分配:為了盡可能降低動態分配extent的弊端,應該如下:
* 使用本地管理表空間的方法。
* 適當的評估segments的大小:確定object的最大size;創建object時,選擇恰當的存儲參數用于分配足夠的空間給相應的data。
* 監控segments的動態extend的情況。
select owner, table_name, blocks, empty_blocks from dba_tables where empty_blocks/(blocks+empty_blocks)<.1;
alter table hr.employees allocate extent;
①創建本地管理extents的tablespace,其實自9i以來,系統默認的表空間都是本地管理的表空間。
create tablespace tsp_name datafile ‘/path/datafile.dbf’ size nM
extent management local uniform size mM;
本地管理表空間在其datafile內部創建一個位圖用于記錄每個block的使用狀態。當extent被分配或釋放重用,bitmap的相應值會被修 改,用于顯示其中blocks的新狀態。這些修改不會產生rollback information,因為沒有修改data dictionary。
②大extents的優點:DBA應該分配適當的size給segments和extents,一般原則是大extents優于小extents,主要表現在:
* large extents在一定程度上降低了segments動態的分配extents的可能性
* large extents可以稍微的提高I/O的性能,因為Oracle server從磁盤讀取一個連續的large extent的多個blocks應該比從幾個small extents不連續的blocks的速度快。為了避免分離的multiblock的讀取,可以考慮將extents設置為 5*DB_FILE_MULTIBLOCK_READ_COUNT。但是對于不經常進行全表掃描的table,這種設置不會有太大的性能改觀。
* 對于非常large的tables,OS在文件大小上的限制可能使DBA不得不將object分配到multiple extents。
* 使用index查找的性能不會受到index是否在一個或多個extents中的影響。
* Extent maps存放了某個segment中所有extents的信息。如果MAXEXTENTS設置為UNLIMITED,這些maps可以存放在多個 blocks中,從性能角度講,應該盡可能在一次I/O中讀取該extent map。此外多個extents也會降低dictionary的性能,因為每個extent都會占用dictionary cache的少量空間。
附注:①在ASSM表空間中,每個segment的 segment header都有一個extent map,記錄著segment所屬的所有extents的第一個塊的位置和區的大小,如果segment header中容納不下所有的extents信息,oracle會另外添加專門的extents map塊,保存segment中extents的位置大小信息。全表掃描時oracle會根據extents map中所記錄的信息,掃描高水標記之下的所有extents的所有blocks.每個extents map block都有一個指向下一個extents map block的地址,segment header中的extents map信息也有指向第一個extents map block的地址.也就是說所有的extents map block構成了一個鏈表.全表掃描時就依據這個鏈表中所記錄的block的位置信息進行掃描.extents map的主要作用是用于全表掃描.
②FLM段(Free List Managed Segment),其段頭存放著段中Extent的信息,包括Extent的起始地址,Extent的長度。如果由于segment擴展過 多,segment header不能容下所有EXTENT的信息,則會用新的稱之為EXTENT MAP BLOCK的塊來專門存放EXTENT的信息。段頭與各Extent Map Block之間用鏈表形式連接起來。它與ASSM中的extent map鏈表作用不同。
③large extents的缺點:因為需要更多連續的blocks,Oracle server可能很難找到足夠的連接的空間用于對其的分配。
3、高水位線(High-Water Mark)
在空間分配中,有兩類空閑blocks:曾經被占用過,但相應的數據被刪除了,這些blocks將被記錄到相應的free list中,當有insert操作時進程reuse,在high-water mark以下;另一類是自分配給相應的segment后,從來沒有被使用過的,所以在high-water mark之上。
①high-water mark:被記錄在segment header block中;在segment被創建時設置:當插入rows時,每次增加five-block;truncate tables會重置high-water mark,但delete不會。
②在table level,可以將high-water 瑪瑞咖之上的空間收回:
alter table t_name deallocate unused …
全表掃描中,Oracle server會讀取high-water mark以下的所有blocks,high-water mark以上的空閑blocks不會影響性能。
③在cluster中,空間是為所有的cluster keys分配的,無論其是否含有data。分配的空間依靠cluster在創建時參數size指定的大小和cluster的類型:
* 在hash cluster中,因為hash keys的數量在cluster被創建是已經被確定了,所以每個hash key所占用的空間都在high-water mark之下。
* 在index cluster中,空間被分配給每個cluster index。
4、table statistics
可以使用analyze語句或是dbms_stats對table的當前狀況進行統計并保存在數據字典中,隨后通過查看dba_tables獲得相關信息。
eg:
analyze table t_name compute statistics;
select num_rows, blocks, empty_blocks as empty, avg_space, chain_cnt, avg_row_len from dba_tables where table_name=’T_NAME’;
其中dba_tables中不同的字段具體含義如下:
Num_Rows – Number of rows in the table
Blocks – Number of blocks below the high-water mark of the table
Empty_blocks – Number of blocks above the high-water mark of the table
Avg_space – Average free space in bytes in the blocks below the highwater mark
Avg_row_len – Average row length, including row overhead
Chain_cnt – Number of chained, or migrated, rows in the table
Avg_space_freelist_blocks – The average freespace of all blocks on a freelist
Num_freelist_blocks – The number of blocks on the freelist
5、DBMS_SPACE包:可用于獲得segments中的space的狀態信息,常用的有以下兩個procedures:
* UNUSED_SPACE:用于獲得分配給object未使用的space。
* FREE_BLOCKS:用于獲得object的空閑的space。在運行時,必須提供相應的FREELIST_GROUP_ID,一般使用1,除非你使用的是Oracle Parallel server。
該DBMS_SPACE包是由dbmsutil.sql創建的。
6、恢復表空間:
1)對于在high-water mark以下的空間:
方法一:export the table;drop or truncate the table;import the table
在選擇是drop還是truncate的時候,要考慮:drop將table在data dictionary中的所有information刪除,并且space被收回;而truncate沒有,并保留了相應已經分配的space等待 reused;如果使用的是data dictionary管理tablespace,則影響空間收回與分配的時間開銷的主要因素是extents的數量(而不是size);如果使用的是 drop方法,則考慮在import時使用compress選項,因為整個空間的分配可能不是在一個連續的大空間上。
方法二:alter table t_name move;此方法執行之后,所有相關的indexes都為unusable狀態,必須rebuild。
2)對于在high-water mark之上的unused block可使用:alter table t_name deallocate unused語句進行收回。
7、DB的block size設置
1)減少訪問block的數量,這是DB tuning的一個目標。DBA對此調節的方法主要有:增大block size;盡可能緊湊的將rows放在block中,避免row的遷移現象。
2)database block size是在DB創建時由參數DB_BLOCK_SIZE指定的,是I/O讀取datafile的最小單元。當前有些OS允許block size達到64KB,可以查看相應的OS,從而調整DB的block size。block size一旦設置就不能改變,除非對DB重建或是duplicate,在9i中已經進行了相應的改進,可以使用多中block sizes,但是對于base data size仍不可變。DB的block size應該是OS的整數倍。如果application中有大量的全表掃描,可以考慮增大block size,但不要超過OS的I/O size。
3)小block size的優劣:
* 優:降低了block 的沖突;有利于small rows;有利于隨機訪問,因為可以在一定程度上提高buffer cache的利用率,特別是在內存資源不足的情況下。
* 劣:small blocks管理所用的空間開銷大;每個block存放的row較少,也會加大I/O的開銷;可能造成更多的index blocks被讀入。
在OLTP環境中,經常存在large object的隨機訪問時,small blocks相對更好。
4)large block size的優劣:
* 優:所用的管理空間開銷小,更多的空間可用于存放具體的data;有利于順序的讀取;有利于large rows;改善了index讀取的性能,因為大的block可以降低index的level數量,從而減少I/O的次數。
* 劣:在OLTP環境中不利于index blocks,可能會引起index leaf blocks的爭用沖突;如果存在大量隨機訪問可能會造成buffer cache的浪費。
在DSS環境中,連續讀取大量數據操作較多,使用large block更好。
8、PCTREE和PCTUSED(具體內容在其他文章中介紹過了,這里不累述了)
只有兩類DML語句可以影響free blocks和used blocks的數量:delete和update。
釋放的空間在一個block中很可能不是連續的,Oracle server只在下面情況同時出現時進行free space的合并:insert或update操作試圖向一個有足夠空間的block中插入數據;free space存在碎片,以至于row piece無法被寫入。
具體設置:
①PCTFREE:默認情況下是10;如果不存在update操作,可以使用0;PCTFREE = 100 * UPD / (Average row length)
②PCTUSED:默認是40;PCTUSED = 100 – PCTFREE – 100 * Rows * ( average row length) / block size
其中:
UPD = update操作平均增加的bytes數量。
average row length和rows都可以在analyze之后從dba_tables表中獲得。
當對一個已經存在的表進行這兩個參數的修改,不會有馬上的影響,只是在后續的DML操作中才發生作用。
9、migration和chaining(具體原因也在其他的文章中介紹過了)
①migration和chaining對性能的影響:一方面,引起這兩種現象的insert和update本身性能比較差;另一方面,在查詢此類記錄的操作會因為額外的I/O造成性能較差。
migration現象過的,主要是由于PCTFREE參數設置過低引起的,對此可以考慮增大該值。
②對兩者的檢測,主要是通過analyze相應的表,隨后從dba_tables表中觀察其chain_cnt字段。此外可以從v$sysstat視圖或 是statspack report中的“instance activity stats for DB”獲得“table fetch continued row”的值。
還可以收集每個表中發生了migration和chaining的具體的rows:首先執行utlchain.sql腳本創建chained_rows統計表,隨后執行語句:
analyze table t_name list chained rows;
③消除migration rows:
* export/import
* alter table t_name move
* 執行遷移腳本,具體見Oracle 9i Performance Tuning SG的P398
• Find migrated rows using ANALYZE.
• Copy migrated rows to new table.
• Delete migrated rows from original table.
• Copy rows from new table to original table.
此方法執行時,必須注意與original table相關的外鍵約束,應將其disable。
10、索引的重組
在經常發生DML的table上,indexes往往是帶來性能問題的原因。
在data blocks中,Oracle server會將delete row釋放的空間重新分配給insert rows,但是對于index blocks,Oracle server的應用時連續的。即使一個index block中只有一個index,也要維護該block。如果刪除了block中的所有index,該block才會被送入free list。因此,必要時需要進行index的rebuild。
①對index space的監控:
* analyze index i_name validate structure;
* select name, (del_lf_rows_len / lf_rows_len) * 100 as wastage from index_stats;
在index_stats視圖中,各字段含義如下:
• Lf_rows – Number of values currently in the index
• Lf_rows_len – Sum of all the length of values, in bytes
• Del_lf_rows – Number of values deleted from the index
• Del_lf_rows_len – Length of all deleted values
note:index_stats視圖只保存最近一次analyze的結果,并且當前session只能看到當前session的分析結果。
* alter index emp_name_ix rebuild;
* alter index emp_name_ix coalesce;
如果如果已刪除的index 記錄超過20%,則應該選用rebuild。
rebuild會以原有的index作為基礎,重建索引,可以重新指定STORAGE, TABLESPACE, INITRANS參數,同時可以用下面的參數加快重建的效率:
* PARALLEL/NOPARALLEL(NOPARALLEL是默認值)
* RECOVERABLE/UNRECOVERABLE ( RECOVERABLE是默認的):當使用unrecoverable時速度將更快,因為它不產生redo log,只在index創建是起作用,而不是設置參數,不記錄到dictionary中。它使用隱含式的logging參數,意味著在index創建結束 后插入index項時,仍然會記錄redo log。
* LOGGING/NOLOGGING:如果設置為NOLOGGING,該參數表明在index運行使用期間,將不產生任何redo log。它將記錄到dictionary中。可以用alter index 進行修改。
注意:unrecoverable和logging是不兼容的。
alter index rebuild要快于index的drop后re-create,因為它使用了full scan的方法。
②監控index的使用情況
* EXECUTE DBMS_STATS.GATHER_INDEX_STATS(‘SECHMA_NAME’, ‘T_NAME’);
* create index … compute statistics;
* alter index .. rebuild compute statistics;
③此外,還可以用下面的方法查看沒有使用的index:
從9i開始,對index的使用情況可以被收集到視圖v$object_usage中。輔助DBA刪除未使用的index,提高性能:
* 打開監控:alter index i_name monitoring usage;
* 停止監控:alter index i_name nomonioring usage;
隨后查看v$object_usage:select index_name, used from v$object_usage;
在v$object_usage中各個字段的意義:
• index_name – The index name
• table_name – The corresponding table
• monitoring – Indicates whether monitoring is “ON or OFF”
• used – Indicates (YES or NO) the index has been used during the monitoring time
• start_monitoring – Time at which monitoring began on index
• stop_monitoring – Time at which monitoring stopped on index
posted on 2010-01-12 12:33 gdufo 閱讀(799) 評論(0) 編輯 收藏 所屬分類: Database (oracle, sqlser,MYSQL)