Oracle大表添加索引的實(shí)現(xiàn)方式
背景
業(yè)務(wù)系統(tǒng)中現(xiàn)在經(jīng)常存在上億數(shù)據(jù)的大表,在這樣的大表上新建索引,是一個(gè)較為耗時(shí)的操作,特別是在生產(chǎn)環(huán)境的系統(tǒng)中,添加不當(dāng),有可能造成業(yè)務(wù)表鎖表,業(yè)務(wù)表長時(shí)間的停服勢必會(huì)影響正常業(yè)務(wù)的開展。
根據(jù)個(gè)人的實(shí)際經(jīng)驗(yàn),我們可以使用三種手段來幫助大家解決這個(gè)問題,需要注意的是這三種方法并不是獨(dú)立使用的,很多時(shí)候我們會(huì)結(jié)合起來一起使用來提升建索引的效率。
解決方案
第一種方法就是使用并行——parallel 開啟并發(fā)執(zhí)行
并發(fā)執(zhí)行可以最大程度的利用我們的數(shù)據(jù)庫的硬件資源,把大批量的數(shù)據(jù)分成小批量到不同的進(jìn)程去執(zhí)行,從而大大減少sql的執(zhí)行的時(shí)間。
由于建索引屬于ddl操作,我們可以通過下面的語句來實(shí)現(xiàn)并發(fā)執(zhí)行。
下面的語句中,我們就配置了使用并發(fā)值為8來執(zhí)行我們的sql語句
CREATE INDEX idx_table1_column1 ON table1 (column1) PARALLEL 8;
注意:
并不是所有的系統(tǒng)都適用使用并行來解決,比如:目前有個(gè)系統(tǒng)使用cpu已經(jīng)很高,如果這時(shí)你再開啟并行,只會(huì)加重系統(tǒng)的負(fù)載。因此,在執(zhí)行并行操作前一定要看一下系統(tǒng)目前使用情況。
第二種方法是不開啟日志——nologging
我們知道數(shù)據(jù)表新增、修改、刪除記錄都可能會(huì)觸發(fā)redo日志和undo日志的記錄,特別是insert into table1 select * from table2這種語句,每條insert動(dòng)作都會(huì)同時(shí)生成redo日志和undo日志,從而降低sql的執(zhí)行速度。
對于創(chuàng)建索引的操作也是如此,索引的創(chuàng)建同樣也涉及到這兩類日志的記錄,我們可以手動(dòng)指定不記錄非必要日志來加快sql執(zhí)行的速度。
注意:
nologging的核心在于只輸入最少的redo日志(注意,這里不是不輸出日志,只是最小化需要輸入的日志量而已) 用法的話十分簡單,只需要在我們創(chuàng)建索引的語句上加上nologging關(guān)鍵字即可
CREATE INDEX idx_table1_column1 ON table1 (column1) nologging;
第三種方法是在線執(zhí)行——online(推薦使用)
前面介紹的兩個(gè)命令雖然能大幅度提升效率,但歸根結(jié)底建索引就是會(huì)導(dǎo)致鎖表,不停服執(zhí)行的話還是相當(dāng)有風(fēng)險(xiǎn)的,online的作用在于不阻塞DML操作,使得生產(chǎn)環(huán)境不會(huì)因?yàn)閳?zhí)行DDL語句導(dǎo)致業(yè)務(wù)功能阻塞, 尤其適合于不停機(jī)新建表索引這類場景。
需要注意的是:
online關(guān)鍵字的使用相對來說耗時(shí)會(huì)長一些,而且online關(guān)鍵字只能用于新增索引,并不能用在修改表結(jié)構(gòu)等SQL語句中。
online的使用也十分簡單,在sql語句后面加上online就行。
CREATE INDEX idx_table1_column1 ON table1 (column1) online;
有了這三個(gè)方法,我們的最終的sql大概是這樣的,有了online可以保障不影響業(yè)務(wù)主流程的進(jìn)行,而nologging和parallel則可以大幅度提高我們sql的執(zhí)行速度,個(gè)人覺得是一種可行的解決方案。
CREATE INDEX idx_table1_column1 ON table1 (column1) parallel 8 nologging online ;
很多朋友認(rèn)為到這里就結(jié)束了,其實(shí)oracle數(shù)據(jù)庫優(yōu)化的空間永無止境,如果有朋友想追求最佳,想把數(shù)據(jù)庫的性能發(fā)揮到最佳。
那么下面還有三種方法,但是這些不常用,作為學(xué)習(xí)數(shù)據(jù)庫的原理,可以了解一下。
補(bǔ)充方法1:
由于創(chuàng)建索引時(shí)需要對表進(jìn)行全表掃描,可以適當(dāng)考慮調(diào)大db_file_multiblock_read_count的值, db_file_multiblock_read_count影響Oracle在讀取數(shù)據(jù)時(shí)一次讀取的最大block數(shù)量,在進(jìn)行一些數(shù)據(jù)量比較大的操作時(shí),可以適當(dāng) 調(diào)整當(dāng)前session的db_file_multiblock_read_count值,會(huì)在IO上節(jié)省節(jié)省一些時(shí)間。
SQL> show parameter db_file NAME TYPE VALUE db_file_multiblock_read_count integer 128 SQL> alter session set db_file_multiblock_read_count=256; Session altered. SQL> show parameter db_file NAME TYPE VALUE db_file_multiblock_read_count integer 256
補(bǔ)充方法2:
我們知道索引都是有序的,利用索引的這個(gè)特性,因此我們可以想到,在創(chuàng)建索引時(shí),要把索引列的值拿到內(nèi)存中進(jìn)行排序,因此我們調(diào)整排序區(qū)的大小(sort_area_size),建立索引時(shí)要對大量數(shù)據(jù)進(jìn)行排序操作 在oracle11g,如果workarea_size_policy的值為AUTO,sort_area_size將被忽略,pga_aggregate_target將被啟用,pga_aggregate_target決定了整個(gè) 的pga大小,而且一個(gè)session并不能使用全部的pga大小,它受到一個(gè)隱藏參數(shù)的限制,大致能使用pga_agregate_target的5%,因此可以 考慮將workarea_size_policy的值為manual,然后設(shè)置較大的sort_area_size以滿足需求。
SQL> alter system set workarea_size_policy=‘MANUAL'; System altered. SQL> alter session set sort_area_size=204800; Session altered. SQL> show parameter sort_area_size; NAME TYPE VALUE sort_area_size integer 204800
補(bǔ)充方法3 :
為了讓添加索引的表能盡快加載到數(shù)據(jù)緩存區(qū)中buffer cache,我們可以使用cache和full hint對源表做fts,以使它盡可能的出現(xiàn)在 buffer cache中LRU的MRU一端。
SQL> select /*+ cache(t) full(t) / count() from big_table t;
打掃戰(zhàn)場:添加完索引后,把打掃一下戰(zhàn)場,把戰(zhàn)場恢復(fù)到操作之前,因此我們要把調(diào)整的參數(shù)進(jìn)行恢復(fù)到原來的樣子。
SQL> alter system set workarea_size_policy=‘AUTO'; System altered. SQL> alter session set db_file_multiblock_read_count = 128; Session altered.
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Oracle數(shù)據(jù)庫存儲過程的調(diào)試過程
oracle如果存儲過程比較復(fù)雜,我們要定位到錯(cuò)誤就比較困難,那么我們就可以用存儲過程的調(diào)試功能,下面這篇文章主要給大家介紹了關(guān)于Oracle數(shù)據(jù)庫存儲過程調(diào)試的相關(guān)資料,需要的朋友可以參考下2022-07-07
CentOS8下安裝oracle客戶端完整(填坑)過程分享(推薦)
這篇文章主要介紹了CentOS8下安裝oracle客戶端完整(填坑)過程分享,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-12-12
Oracle9i數(shù)據(jù)庫異常關(guān)閉后的啟動(dòng)
Oracle9i數(shù)據(jù)庫異常關(guān)閉后的啟動(dòng)...2007-03-03
oracle設(shè)置mybatis自動(dòng)生成id插入方式
這篇文章主要介紹了oracle設(shè)置mybatis自動(dòng)生成id插入方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07
解析如何查看Oracle數(shù)據(jù)庫中某張表的字段個(gè)數(shù)
本篇文章是對查看Oracle數(shù)據(jù)庫中某張表的字段個(gè)數(shù)進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06
oracle如何使用java source調(diào)用外部程序
這篇文章主要為大家介紹了oracle如何使用java source調(diào)用外部程序,感興趣的小伙伴們可以參考一下2016-09-09

