22、在SQL2000以前,一般不要用如下的字句: "IS NULL", "<>", "!=", "!>", "!<", "NOT", "NOT EXISTS", "NOT IN", "NOT LIKE", and "LIKE '%500'",因為他們不走索引全是表掃描。也不要在Where字句中的列名加函數,如Convert,substring等,如果必須用函數的時候,創建計算列再創建索引來替代.還可以變通寫法:Where SUBSTRING(firstname,1,1) = 'm'改為Where firstname like 'm%'(索引掃描),一定要將函數和列名分開。并且索引不能建得太多和太大。NOT IN會多次掃描表,使用EXISTS、NOT EXISTS ,IN , LEFT OUTER JOIN 來替代,特別是左連接,而Exists比IN更快,最慢的是NOT操作.如果列的值含有空,以前它的索引不起作用,現在2000的優化器能夠處理了。相同的是IS NULL,"NOT", "NOT EXISTS", "NOT IN"能優化她,而"<>"等還是不能優化,用不到索引。
23、使用Query Analyzer,查看SQL語句的查詢計劃和評估分析是否是優化的SQL。一般的20%的代碼占據了80%的資源,我們優化的重點是這些慢的地方。
24、如果使用了IN或者OR等時發現查詢沒有走索引,使用顯示申明指定索引: Select * FROM PersonMember (INDEX = IX_Title) Where processid IN ('男','女')
25、將需要查詢的結果預先計算好放在表中,查詢的時候再Select。這在SQL7.0以前是最重要的手段。例如醫院的住院費計算。
26、MIN() 和 MAX()能使用到合適的索引。
27、數據庫有一個原則是代碼離數據越近越好,所以優先選擇Default,依次為Rules,Triggers, Constraint(約束如外健主健CheckUNIQUE……,數據類型的最大長度等等都是約束),Procedure.這樣不僅維護工作小,編寫程序質量高,并且執行的速度快。
28、如果要插入大的二進制值到Image列,使用存儲過程,千萬不要用內嵌Insert來插入(不知JAVA是否)。因為這樣應用程序首先將二進制值轉換成字符串(尺寸是它的兩倍),服務器受到字符后又將他轉換成二進制值.存儲過程就沒有這些動作: 方法:Create procedure p_insert as insert into table(Fimage) values (@image), 在前臺調用這個存儲過程傳入二進制參數,這樣處理速度明顯改善。
29、Between在某些時候比IN 速度更快,Between能夠更快地根據索引找到范圍。用查詢優化器可見到差別。 select * from chineseresume where title in ('男','女') Select * from chineseresume where between '男' and '女' 是一樣的。由于in會在比較多次,所以有時會慢些。
30、在必要是對全局或者局部臨時表創建索引,有時能夠提高速度,但不是一定會這樣,因為索引也耗費大量的資源。他的創建同是實際表一樣。
31、不要建沒有作用的事物例如產生報表時,浪費資源。只有在必要使用事物時使用它。
32、用OR的字句可以分解成多個查詢,并且通過UNION 連接多個查詢。他們的速度只同是否使用索引有關,如果查詢需要用到聯合索引,用UNION all執行的效率更高.多個OR的字句沒有用到索引,改寫成UNION的形式再試圖與索引匹配。一個關鍵的問題是否用到索引。
33、盡量少用視圖,它的效率低。對視圖操作比直接對表操作慢,可以用stored procedure來代替她。特別的是不要用視圖嵌套,嵌套視圖增加了尋找原始資料的難度。我們看視圖的本質:它是存放在服務器上的被優化好了的已經產生了查詢規劃的SQL。對單個表檢索數據時,不要使用指向多個表的視圖,直接從表檢索或者僅僅包含這個表的視圖上讀,否則增加了不必要的開銷,查詢受到干擾.為了加快視圖的查詢,MsSQL增加了視圖索引的功能。
34、沒有必要時不要用DISTINCT和ORDER BY,這些動作可以改在客戶端執行。它們增加了額外的開銷。這同UNION 和UNION ALL一樣的道理。
select top 20 ad.companyname,comid,position,ad.referenceid,worklocation, convert(varchar(10),ad.postDate,120) as postDate1,workyear,degreedescription FROM jobcn_query.dbo.COMPANYAD_query ad where referenceID in('JCNAD00329667','JCNAD132168','JCNAD00337748','JCNAD00338345',
'JCNAD00333138','JCNAD00303570','JCNAD00303569',
'JCNAD00303568','JCNAD00306698','JCNAD00231935','JCNAD00231933',
'JCNAD00254567','JCNAD00254585','JCNAD00254608',
'JCNAD00254607','JCNAD00258524','JCNAD00332133','JCNAD00268618',
'JCNAD00279196','JCNAD00268613') order by postdate desc
35、在IN后面值的列表中,將出現最頻繁的值放在最前面,出現得最少的放在最后面,減少判斷的次數。
36、當用Select INTO時,它會鎖住系統表(sysobjects,sysindexes等等),阻塞其他的連接的存取。創建臨時表時用顯示申明語句,而不是 select INTO. drop table t_lxh begin tran select * into t_lxh from chineseresume where name = 'XYZ' --commit 在另一個連接中Select * from sysobjects可以看到 Select INTO 會鎖住系統表,Create table 也會鎖系統表(不管是臨時表還是系統表)。所以千萬不要在事物內使用它。!這樣的話如果是經常要用的臨時表請使用實表,或者臨時表變量。
37、一般在GROUP BY 個HAVING字句之前就能剔除多余的行,所以盡量不要用它們來做剔除行的工作。他們的執行順序應該如下最優:select 的Where字句選擇所有合適的行,Group By用來分組個統計行,Having字句用來剔除多余的分組。這樣Group By 個Having的開銷小,查詢快.對于大的數據行進行分組和Having十分消耗資源。如果Group BY的目的不包括計算,只是分組,那么用Distinct更快
38、一次更新多條記錄比分多次更新每次一條快,就是說批處理好
39、少用臨時表,盡量用結果集和Table類性的變量來代替它,Table 類型的變量比臨時表好
40、在SQL2000下,計算字段是可以索引的,需要滿足的條件如下:
a、計算字段的表達是確定的
b、不能用在TEXT,Ntext,Image數據類型
c、必須配制如下選項 ANSI_NULLS = ON, ANSI_PADDINGS = ON, …….
41、盡量將數據的處理工作放在服務器上,減少網絡的開銷,如使用存儲過程。存儲過程是編譯好、優化過、并且被組織到一個執行規劃里、且存儲在數據庫中的SQL語句,是控制流語言的集合,速度當然快。反復執行的動態SQL,可以使用臨時存儲過程,該過程(臨時表)被放在Tempdb中。以前由于SQL SERVER對復雜的數學計算不支持,所以不得不將這個工作放在其他的層上而增加網絡的開銷。SQL2000支持UDFs,現在支持復雜的數學計算,函數的返回值不要太大,這樣的開銷很大。用戶自定義函數象光標一樣執行的消耗大量的資源,如果返回大的結果采用存儲過程
42、不要在一句話里再三的使用相同的函數,浪費資源,將結果放在變量里再調用更快
43、Select COUNT(*)的效率教低,盡量變通他的寫法,而EXISTS快.同時請注意區別: select count(Field of null) from Table 和 select count(Field of NOT null) from Table 的返回值是不同的。!
44、當服務器的內存夠多時,配制線程數量 = 最大連接數+5,這樣能發揮最大的效率;否則使用 配制線程數量<最大連接數啟用SQL SERVER的線程池來解決,如果還是數量 = 最大連接數+5,嚴重的損害服務器的性能。
45、按照一定的次序來訪問你的表。如果你先鎖住表A,再鎖住表B,那么在所有的存儲過程中都要按照這個順序來鎖定它們。如果你(不經意的)某個存儲過程中先鎖定表B,再鎖定表A,這可能就會導致一個死鎖。如果鎖定順序沒有被預先詳細的設計好,死鎖很難被發現
46、通過SQL Server Performance Monitor監視相應硬件的負載 Memory: Page Faults / sec計數器如果該值偶爾走高,表明當時有線程競爭內存。如果持續很高,則內存可能是瓶頸。
Process:
1、% DPC Time 指在范例間隔期間處理器用在緩延程序調用(DPC)接收和提供服務的百分比。(DPC 正在運行的為比標準間隔優先權低的間隔)。 由于 DPC 是以特權模式執行的,DPC 時間的百分比為特權時間百分比的一部分。這些時間單獨計算并且不屬于間隔計算總數的一部 分。這個總數顯示了作為實例時間百分比的平均忙時。
2、%Processor Time計數器 如果該參數值持續超過95%,表明瓶頸是CPU?梢钥紤]增加一個處理器或換一個更快的處理器。
3、% Privileged Time 指非閑置處理器時間用于特權模式的百分比。(特權模式是為操作系統組件和操縱硬件驅動程序而設計的一種處理模式。它允許直接訪問硬件和所有內存。另一種模式為用戶模式,它是一種為應用程序、環境分系統和整數分系統設計的一種有限處理模式。操作系統將應用程序線程轉換成特權模式以訪問操作系統服務)。特權時間的 % 包括為間斷和 DPC 提供服務的時間。特權時間比率高可能是由于失敗設備產生的大數量的間隔而引起的。這個計數器將平均忙時作為樣本時間的一部分顯示。
4、% User Time表示耗費CPU的數據庫操作,如排序,執行aggregate functions等。如果該值很高,可考慮增加索引,盡量使用簡單的表聯接,水平分割大表格等方法來降低該值。 Physical Disk: Curretn Disk Queue Length計數器該值應不超過磁盤數的1.5~2倍。要提高性能,可增加磁盤。
SQLServer:Cache Hit Ratio計數器該值越高越好。如果持續低于80%,應考慮增加內存。 注意該參數值是從SQL Server啟動后,就一直累加記數,所以運行經過一段時間后,該值將不能反映系統當前值。
47、分析select emp_name form employee where salary > 3000 在此語句中若salary是Float類型的,則優化器對其進行優化為Convert(float,3000),因為3000是個整數,我們應在編程時使用3000.0而不要等運行時讓DBMS進行轉化。同樣字符和整型數據的轉換。
48、查詢的關聯同寫的順序
select a.personMemberID, * from chineseresume a,personmember b where personMemberID = b.referenceid and a.personMemberID = 'JCNPRH39681' (A = B ,B = '號碼')
select a.personMemberID, * from chineseresume a,personmember b where a.personMemberID = b.referenceid and a.personMemberID = 'JCNPRH39681' and b.referenceid = 'JCNPRH39681' (A = B ,B = '號碼', A = '號碼')
select a.personMemberID, * from chineseresume a,personmember b where b.referenceid = 'JCNPRH39681' and a.personMemberID = 'JCNPRH39681' (B = '號碼', A = '號碼')
49、
(1)IF 沒有輸入負責人代碼 THEN code1=0 code2=9999 ELSE code1=code2=負責人代碼 END IF 執行SQL語句為: Select 負責人名 FROM P2000 Where 負責人代碼>=:code1 AND負責人代碼 <=:code2
(2)IF 沒有輸入負責人代碼 THEN Select 負責人名 FROM P2000 ELSE code= 負責人代碼 Select 負責人代碼 FROM P2000 Where 負責人代碼=:code END IF 第一種方法只用了一條SQL語句,第二種方法用了兩條SQL語句。在沒有輸入負責人代碼時,第二種方法顯然比第一種方法執行效率高,因為它沒有限制條件; 在輸入了負責人代碼時,第二種方法仍然比第一種方法效率高,不僅是少了一個限制條件,還因相等運算是最快的查詢運算。我們寫程序不要怕麻煩
50、關于JOBCN現在查詢分頁的新方法(如下),用性能優化器分析性能的瓶頸,如果在I/O或者網絡的速度上,如下的方法優化切實有效,如果在CPU或者內存上,用現在的方法更好。請區分如下的方法,說明索引越小越好。
begin
DECLARE @local_variable table (FID int identity(1,1),ReferenceID varchar(20))
insert into @local_variable (ReferenceID)
select top 100000 ReferenceID from chineseresume order by ReferenceID
select * from @local_variable where Fid > 40 and fid <= 60
end 和
begin
DECLARE @local_variable table (FID int identity(1,1),ReferenceID varchar(20))
insert into @local_variable (ReferenceID)
select top 100000 ReferenceID from chineseresume order by updatedate
select * from @local_variable where Fid > 40 and fid <= 60
end 的不同
begin
create table #temp (FID int identity(1,1),ReferenceID varchar(20))
insert into #temp (ReferenceID)
select top 100000 ReferenceID from chineseresume order by updatedate
select * from #temp where Fid > 40 and fid <= 60 drop table #temp
end
存儲過程編寫經驗和優化措施
一)、適合讀者對象:數據庫開發程序員,數據庫的數據量很多,涉及到對SP(存儲過程)的優化的項目開發人員,對數據庫有濃厚興趣的人。
二)、介紹:在數據庫的開發過程中,經常會遇到復雜的業務邏輯和對數據庫的操作,這個時候就會用SP來封裝數據庫操作。如果項目的SP較多,書寫又沒有一定的規范,將會影響以后的系統維護困難和大SP邏輯的難以理解,另外如果數據庫的數據量大或者項目對SP的性能要求很,就會遇到優化的問題,否則速度有可能很慢,經過親身經驗,一個經過優化過的SP要比一個性能差的SP的效率甚至高幾百倍。
三)、內容:
1、開發人員如果用到其他庫的Table或View,務必在當前庫中建立View來實現跨庫操作,最好不要直接使用“databse.dbo.table_name”,因為sp_depends不能顯示出該SP所使用的跨庫table或view,不方便校驗!
2、開發人員在提交SP前,必須已經使用set showplan on分析過查詢計劃,做過自身的查詢優化檢查。
3、高程序運行效率,優化應用程序,在SP編寫過程中應該注意以下幾點:
a)SQL的使用規范:
i. 盡量避免大事務操作,慎用holdlock子句,提高系統并發能力。
ii. 盡量避免反復訪問同一張或幾張表,尤其是數據量較大的表,可以考慮先根據條件提取數據到臨時表中,然后再做連接。
iii. 盡量避免使用游標,因為游標的效率較差,如果游標操作的數據超過1萬行,那么就應該改寫;如果使用了游標,就要盡量避免在游標循環中再進行表連接的操作。
iv. 注意where字句寫法,必須考慮語句順序,應該根據索引順序、范圍大小來確定條件子句的前后順序,盡可能的讓字段順序與索引順序相一致,范圍從大到小。
v. 不要在where子句中的“=”左邊進行函數、算術運算或其他表達式運算,否則系統將可能無法正確使用索引。
vi. 盡量使用exists代替select count(1)來判斷是否存在記錄,count函數只有在統計表中所有行數時使用,而且count(1)比count(*)更有效率。
vii. 盡量使用“>=”,不要使用“>”。
viii. 注意一些or子句和union子句之間的替換
ix. 注意表之間連接的數據類型,避免不同類型數據之間的連接。
x. 注意存儲過程中參數和數據類型的關系。
xi. 注意insert、update操作的數據量,防止與其他應用沖突。如果數據量超過200個數據頁面(400k),那么系統將會進行鎖升級,頁級鎖會升級成表級鎖。
b)索引的使用規范:
i. 索引的創建要與應用結合考慮,建議大的OLTP表不要超過6個索引。
ii. 盡可能的使用索引字段作為查詢條件,尤其是聚簇索引,必要時可以通過index index_name來強制指定索引
iii. 避免對大表查詢時進行table scan,必要時考慮新建索引。
iv. 在使用索引字段作為條件時,如果該索引是聯合索引,那么必須使用到該索引中的第一個字段作為條件時才能保證系統使用該索引,否則該索引將不會被使用。
v. 要注意索引的維護,周期性重建索引,重新編譯存儲過程!
c)tempdb的使用規范:
i. 盡量避免使用distinct、order by、group by、having、join、cumpute,因為這些語句會加重tempdb的負擔。
ii. 避免頻繁創建和刪除臨時表,減少系統表資源的消耗。
iii. 在新建臨時表時,如果一次性插入數據量很大,那么可以使用select into代替create table,避免log,提高速度;如果數據量不大,為了緩和系統表的資源,建議先create table,然后insert。
iv. 如果臨時表的數據量較大,需要建立索引,那么應該將創建臨時表和建立索引的過程放在單獨一個子存儲過程中,這樣才能保證系統能夠很好的使用到該臨時表的索引。
v. 如果使用到了臨時表,在存儲過程的最后務必將所有的臨時表顯式刪除,先truncate table,然后drop table,這樣可以避免系統表的較長時間鎖定。
vi. 慎用大的臨時表與其他大表的連接查詢和修改,減低系統表負擔,因為這種操作會在一條語句中多次使用tempdb的系統表!
d)合理的算法使用:
根據上面已提到的SQL優化技術和ASE Tuning手冊中的SQL優化內容,結合實際應用,采用多種算法進行比較,以獲得消耗資源最少、效率最高的方法。具體可用ASE調優命令:set statistics io on, set statistics time on , set showplan on 等。
51、SET SHOWPLAN_ALL ON 查看執行方案。DBCC檢查數據庫數據完整性。DBCC(DataBase Consistency Checker)是一組用于驗證SQL Server數據庫完整性的程序。
52、謹慎使用游標
在某些必須使用游標的場合,可考慮將符合條件的數據行轉入臨時表中,再對臨時表定義游標進行操作,這樣可使性能得到明顯提高。
Oracle SQL 性能優化:
1.選用適合的ORACLE優化器
ORACLE的優化器共有3種
A、RULE (基于規則) b、COST (基于成本) c、CHOOSE (選擇性)
設置缺省的優化器,可以通過對init.ora文件中OPTIMIZER_MODE參數的各種聲明,如RULE,COST,CHOOSE,ALL_ROWS,FIRST_ROWS 。 你當然也在SQL句級或是會話(session)級對其進行覆蓋。
為了使用基于成本的優化器(CBO, Cost-Based Optimizer) , 你必須經常運行analyze 命令,以增加數據庫中的對象統計信息(object statistics)的準確性。
如果數據庫的優化器模式設置為選擇性(CHOOSE),那么實際的優化器模式將和是否運行過analyze命令有關。 如果table已經被analyze過, 優化器模式將自動成為CBO , 反之,數據庫將采用RULE形式的優化器。
在缺省情況下,ORACLE采用CHOOSE優化器, 為了避免那些不必要的全表掃描(full table scan) , 你必須盡量避免使用CHOOSE優化器,而直接采用基于規則或者基于成本的優化器。
2.訪問Table的方式
ORACLE 采用兩種訪問表中記錄的方式:
A、 全表掃描
全表掃描就是順序地訪問表中每條記錄。ORACLE采用一次讀入多個數據塊(database block)的方式優化全表掃描。
B、 通過ROWID訪問表
你可以采用基于ROWID的訪問方式情況,提高訪問表的效率, ROWID包含了表中記錄的物理位置信息。ORACLE采用索引(INDEX)實現了數據和存放數據的物理位置(ROWID)之間的聯系。通常索引提供了快速訪問ROWID的方法,因此那些基于索引列的查詢就可以得到性能上的提高。
3.共享SQL語句
為了不重復解析相同的SQL語句,在第一次解析之后,ORACLE將SQL語句存放在內存中。這塊位于系統全局區域SGA(system global area)的共享池(shared buffer pool)中的內存可以被所有的數據庫用戶共享。 因此,當你執行一個SQL語句(有時被稱為一個游標)時,如果它和之前的執行過的語句完全相同, ORACLE就能很快獲得已經被解析的語句以及最好的執行路徑。ORACLE的這個功能大大地提高了SQL的執行性能并節省了內存的使用。
可惜的是ORACLE只對簡單的表提供高速緩沖(cache buffering),這個功能并不適用于多表連接查詢。
數據庫管理員必須在init.ora中為這個區域設置合適的參數,當這個內存區域越大,就可以保留更多的語句,當然被共享的可能性也就越大了。
當你向ORACLE提交一個SQL語句,ORACLE會首先在這塊內存中查找相同的語句。這里需要注明的是,ORACLE對兩者采取的是一種嚴格匹配,要達成共享,SQL語句必須完全相同(包括空格,換行等)。
數據庫管理員必須在init.ora中為這個區域設置合適的參數,當這個內存區域越大,就可以保留更多的語句,當然被共享的可能性也就越大了。
共享的語句必須滿足三個條件:
A、 字符級的比較: 當前被執行的語句和共享池中的語句必須完全相同。
B、 兩個語句所指的對象必須完全相同:
C、 兩個SQL語句中必須使用相同的名字的綁定變量(bind variables)。
4.選擇最有效率的表名順序(只在基于規則的優化器中有效)
ORACLE的解析器按照從右到左的順序處理FROM子句中的表名,因此FROM子句中寫在最后的表(基礎表 driving table)將被最先處理。在FROM子句中包含多個表的情況下,你必須選擇記錄條數最少的表作為基礎表。當ORACLE處理多個表時, 會運用排序及合并的方式連接它們。首先,掃描第一個表(FROM子句中最后的那個表)并對記錄進行派序,然后掃描第二個表(FROM子句中最后第二個表),最后將所有從第二個表中檢索出的記錄與第一個表中合適記錄進行合并。
如果有3個以上的表連接查詢, 那就需要選擇交叉表(intersection table)作為基礎表, 交叉表是指那個被其他表所引用的表。
5.WHERE子句中的連接順序
ORACLE采用自下而上的順序解析WHERE子句,根據這個原理,表之間的連接必須寫在其他WHERE條件之前, 那些可以過濾掉最大數量記錄的條件必須寫在WHERE子句的末尾。
6.SELECT子句中避免使用 ' * '
當你想在SELECT子句中列出所有的COLUMN時,使用動態SQL列引用 '*' 是一個方便的方法。不幸的是,這是一個非常低效的方法。實際上,ORACLE在解析的過程中, 會將'*' 依次轉換成所有的列名, 這個工作是通過查詢數據字典完成的, 這意味著將耗費更多的時間。
7.減少訪問數據庫的次數
當執行每條SQL語句時,ORACLE在內部執行了許多工作:解析SQL語句,估算索引的利用率,綁定變量,讀數據塊等等。由此可見,減少訪問數據庫的次數,就能實際上減少ORACLE的工作量。
8.使用DECODE函數來減少處理時間
使用DECODE函數可以避免重復掃描相同記錄或重復連接相同的表。
9.整合簡單,無關聯的數據庫訪問
如果你有幾個簡單的數據庫查詢語句,你可以把它們整合到一個查詢中(即使它們之間沒有關系)
10.刪除重復記錄
11.用TRUNCATE替代DELETE
當刪除表中的記錄時,在通常情況下, 回滾段(rollback segments ) 用來存放可以被恢復的信息。 如果你沒有COMMIT事務,ORACLE會將數據恢復到刪除之前的狀態(準確地說是恢復到執行刪除命令之前的狀況)。
而當運用TRUNCATE時, 回滾段不再存放任何可被恢復的信息。當命令運行后,數據不能被恢復。因此很少的資源被調用,執行時間也會很短。
12.盡量多使用COMMIT
只要有可能,在程序中盡量多使用COMMIT,這樣程序的性能得到提高,需求也會因為COMMIT所釋放的資源而減少
COMMIT所釋放的資源:
A、 回滾段上用于恢復數據的信息。
B、被程序語句獲得的鎖。
C、 redo log buffer 中的空間。
D、ORACLE為管理上述3種資源中的內部花費。
13.計算記錄條數
和一般的觀點相反,count(*) 比count(1)稍快,當然如果可以通過索引檢索,對索引列的計數仍舊是最快的。例如 COUNT(EMPNO)
14.用Where子句替換HAVING子句
避免使用HAVING子句,HAVING 只會在檢索出所有記錄之后才對結果集進行過濾。 這個處理需要排序,總計等操作。如果能通過WHERE子句限制記錄的數目,那就能減少這方面的開銷。
15.減少對表的查詢
在含有子查詢的SQL語句中,要特別注意減少對表的查詢。
16.通過內部函數提高SQL效率。
17.使用表的別名(Alias)
當在SQL語句中連接多個表時, 請使用表的別名并把別名前綴于每個Column上。這樣一來,就可以減少解析的時間并減少那些由Column歧義引起的語法錯誤。
18.用EXISTS替代IN
在許多基于基礎表的查詢中,為了滿足一個條件,往往需要對另一個表進行聯接。在這種情況下,使用EXISTS(或NOT EXISTS)通常將提高查詢的效率。
19.用NOT EXISTS替代NOT IN
在子查詢中,NOT IN子句將執行一個內部的排序和合并。 無論在哪種情況下,NOT IN都是最低效的 (因為它對子查詢中的表執行了一個全表遍歷)。為了避免使用NOT IN ,我們可以把它改寫成外連接(Outer Joins)或NOT EXISTS。
20.用表連接替換EXISTS
通常來說 , 采用表連接的方式比EXISTS更有效率 。
21.用EXISTS替換DISTINCT
當提交一個包含一對多表信息(比如部門表和雇員表)的查詢時,避免在SELECT子句中使用DISTINCT。 一般可以考慮用EXIST替換 。
DB2數據庫優化
為了幫助 DB2 DBA 避免性能災難并獲得高性能,我為我們的客戶、用戶和 DB2 專家同行總結了一套故障診斷流程。以下詳細說明在 Unix、Windows 和 OS/2 環境下使用 DB2 UDB 的電子商務 OLTP 應用程序的 10 條最重要的性能改善技巧 - 并在本文的結束部分作出 總結。
每隔大約幾個星期,我們就會接到苦惱的 DBA 們的電話,抱怨有關性能的問題!拔覀 Web 站點速度慢得像蝸牛一樣”,他們叫苦道,“我們正在失去客戶,情況嚴重。你能幫忙嗎?”為了回答這些問題,我為我的咨詢公司開發了一個分析流程,它能讓我們很快找到性能問題的原因,開發出補救措施并提出調整意見。這些打電話的人極少詢問費用和成本 - 他們只關心制止損失。當 DB2 或電子商務應用程序的運行不能達到預期的性能時,組織和財務的收益將遭受極大的損失。
1. 監視開關
確保已經打開監視開關。如果它們沒有打開,您將無法獲取您需要的性能信息。要打開該監視開關,請發出以下命令:
db2 "update monitor switches using
lock ON sort ON bufferpool ON uow ON
table ON statement ON"
2. 代理程序
確保有足夠的 DB2 代理程序來處理工作負載。要找出代理程序的信息,請發出命令:
db2 "get snapshot for database manager"
并查找以下行:
High water mark for agents registered = 7
High water mark for agents waiting for a token = 0
Agents registered= 7
Agents waiting for a token= 0
Idle agents= 5
Agents assigned from pool= 158
Agents created from empty Pool = 7
Agents stolen from another application= 0
High water mark for coordinating agents= 7
Max agents overflow= 0
如果您發現Agents waiting for a token或Agents stolen from another application不為 0,那么請增加對數據庫管理器可用的代理程序數(MAXAGENTS 和/或 MAX_COORDAGENTS取適用者)。
3. 最大打開的文件數
DB2 在操作系統資源的約束下盡量做一個“優秀公民”。它的一個“優秀公民”的行動就是給在任何時刻打開文件的最大數設置一個上限。數據庫配置參數MAXFILOP約束 DB2 能夠同時打開的文件最大數量。當打開的文件數達到此數量時,DB2 將開始不斷地關閉和打開它的表空間文件(包括裸設備)。不斷地打開和關閉文件減緩了 SQL 響應時間并耗費了 CPU 周期。要查明 DB2 是否正在關閉文件,請發出以下命令:
db2 "get snapshot for database on DBNAME"
并查找以下的行:
Database files closed = 0
如果上述參數的值不為 0,那么增加MAXFILOP的值直到不斷打開和關閉文件的狀態停。使用翼嵚命令?/P>
db2 "update db cfg for DBNAME using MAXFILOP N"
4. 鎖
LOCKTIMEOUT的缺省值是 -1,這意味著將沒有鎖超時(對 OLTP 應用程序,這種情況可能會是災難性的)。盡管如此,我還是經常發現許多 DB2 用戶用LOCKTIMEOUT= -1。將LOCKTIMEOUT設置為很短的時間值,例如 10 或 15 秒。在鎖上等待過長時間會在鎖上產生雪崩效應。
首先,用以下命令檢查LOCKTIMEOUT的值:
db2 "get db cfg for DBNAME"
并查找包含以下文本的行:
Lock timeout (sec) (LOCKTIMEOUT) = -1
如果值是 -1,考慮使用以下命令將它更改為 15 秒(一定要首先詢問應用程序開發者或您的供應商以確保應用程序能夠處理鎖超時):
db2 "update db cfg for DBNAME using LOCKTIMEOUT 15"
您同時應該監視鎖等待的數量、鎖等待時間和正在使用鎖列表內存(lock list memory)的量。請發出以下命令:
db2 "get snapshot for database on DBNAME"
查找以下行:
Locks held currently= 0
Lock waits= 0
Time database waited on locks (ms)= 0
Lock list memory in use (Bytes)= 576
Deadlocks detected= 0
Lock escalations= 0
Exclusive lock escalations= 0
Agents currently waiting on locks= 0
Lock Timeouts= 0
如果Lock list memory in use (Bytes)超過所定義LOCKLIST大小的 50%,那么在LOCKLIST數據庫配置中增加 4k 頁的數量。
5. 臨時表空間
為了改善 DB2 執行并行 I/O 和提高使用TEMPSPACE的排序、散列連接(hash join)和其它數據庫操作的性能,臨時表空間至少應該在三個不同的磁盤驅動器上擁有三個容器。
要想知道您的臨時表空間具有多少容器,請發出以下命令:
db2 "list tablespaces show detail"
查找與以下示例類似的TEMPSPACE表空間定義:
Tablespace ID= 1
Name= TEMPSPACE1
Type= System managed space
Contents= Temporary data
State= 0x0000
Detailed explanation: Normal
Total pages= 1
Useable pages= 1
Used pages= 1
Free pages= Not applicable
High water mark (pages)= Not applicable
Page size (bytes)= 4096
Extent size (pages)= 32
Prefetch size (pages)= 96
Number of containers= 3
注意Number of containers的值是 3,而且Prefetch size是Extent size的三倍。為了得到最佳的并行 I/O 性能,重要的是Prefetch size為Extent size的倍數。這個倍數應該等于容器的個數。
要查找容器的定義,請發出以下命令:
db2 "list tablespace containers for 1 show detail"
1 指的是tablespace ID #1,它是剛才所給出的示例中的TEMPSPACE1。
6. 內存排序
OLTP 應用程序不應該執行大的排序。它們在 CPU、I/O 和所用時間方面的成本極高,而且將使任何 OLTP 應用程序慢下來。因此,256 個 4K 頁(1MB)的缺省SORTHEAP大小(1MB)應該是足夠了。您也應該知道排序溢出的數量和每個事務的排序數。
請發出以下命令:
Db2 "get snapshot for database on DBNAME"
并查找以下行:
Total sort heap allocated= 0
Total sorts = 1
Total sort time (ms)= 8
Sort overflows = 0
Active sorts = 0
Commit statements attempted = 3
Rollback statements attempted = 0
Let transactions = Commit statements attempted + Rollback
statements attempted
Let SortsPerTX= Total sorts / transactions
Let PercentSortOverflows = Sort overflows * 100 / Total sorts
如果PercentSortOverflows ((Sort overflows * 100) / Total sorts )大于 3 個百分點,那么在應用程序 SQL 中會出現嚴重的或意外的排序問題。因為正是溢出的存在表明發生了大的排序,所以理想的情況是發現沒有排序溢出或至少其百分比小于一個百分點。
如果出現過多的排序溢出,那么“應急”解決方案是增加SORTHEAP的大小。然而,這樣做只是掩蓋了真實的性能問題。相反,您應該確定引起排序的 SQL 并更改該 SQL、索引或群集來避免或減少排序開銷。
如果SortsPerTX大于 5 (作為一種經驗之談),那么每個事務的排序數可能很大。雖然某些應用程序事務執行許多小的組合排序(它們不會溢出并且執行時間很短),但是它消耗了過多的 CPU。當SortsPerTX很大時,按我的經驗,這些機器通常會受到 CPU 的限制。確定引起排序的 SQL 并改進存取方案(通過索引、群集或更改 SQL)對提高事務吞吐率是極為重要的。
7. 表訪問
對于每個表,確定 DB2 為每個事務讀取的行數。您必須發出兩個命令:
db2 "get snapshot for database on DBNAME"
db2 "get snapshot for tables on DBNAME"
在發出第一個命令以后,確定發生了多少個事務(通過取Commit statements attempted和Rollback statements attempted之和 - 請參閱技巧 3)。
在發出第二個命令以后,將讀取的行數除以事務數(RowsPerTX)。在每個事務中,OLTP 應用程序通常應該從每個表讀取 1 到 20 行。如果您發現對每個事務有成百上千的行正被讀取,那么發生了掃描操作,也許需要創建索引。(有時以分布和詳細的索引來運行 runstats 也可提供了一個解決的辦法。)
“get snapshot for tables on DBNAME”的樣本輸出如下:
Snapshot timestamp = 09-25-2000
4:47:09.970811
Database name= DGIDB
Database path= /fs/inst1/inst1/NODE0000/SQL00001/
Input database alias= DGIDB
Number of accessed tables= 8
Table List
Table Schema= INST1
Table Name= DGI_
SALES_ LOGS_TB
Table Type= User
Rows Written= 0
Rows Read= 98857
Overflows= 0
Page Reorgs= 0
Overflows 的數量很大就可能意味著您需要重組表。當由于更改了行的寬度從而 DB2 必須在一個不夠理想的頁上定位一個行時就會發生溢出。
8. 表空間分析
表空間快照對理解訪問什么數據以及如何訪問是極其有價值的。要得到一個表空間快照,請發出以下命令:
db2 "get snapshot for tablespaces on DBNAME"
對每個表空間,回答以下問題:
平均讀取時間(ms)是多少?
平均寫入時間(ms)是多少?
異步(預取)相對于同步(隨機)所占的物理 I/O 的百分比是多少?
每個表空間的緩沖池命中率是多少?
每分鐘讀取多少物理頁面?
對于每個事務要讀取多少物理和邏輯頁面?
對于所有表空間,回答以下問題:
哪個表空間的讀取和寫入的時間最慢?為什么?是因為其容器在慢速的磁盤上嗎?容器大小是否相等?對比異步訪問和同步訪問,訪問屬性是否和期望的一致?隨機讀取的表應該有隨機讀取的表空間,這是為了得到高的同步讀取百分比、通常較高的緩沖池命中率和更低的物理 I/O 率。
對每個表空間,確保預取大小等于數據塊大小乘以容器數。請發出以下命令:
db2 "list tablespaces show detail"
如果需要,可以為一個給定表空間改變預取大小?梢允褂靡韵旅顏頇z查容器定義:
db2 "list tablespace containers for N show detail"
在此,N 是表空間標識號。
9. 緩沖池優化
我時常發現一些 DB2 UDB 站點,雖然機器具有 2、4 或 8GB 內存,但是 DB2 數據庫卻只有一個緩沖池(IBMDEFAULTBP),其大小只有 16MB!
如果在您的站點上也是這種情況,請為 SYSCATSPACE 目錄表空間創建一個緩沖池、為TEMPSPACE表空間創建一個緩沖池以及另外創建至少兩個緩沖池:BP_RAND和BP_SEQ。隨機訪問的表空間應該分配給用于隨機訪問的緩沖池(BP_RAND)。順序訪問(使用異步預取 I/O)的表空間應該分配給用于順序訪問的緩沖池(BP_SEQ)。根據某些事務的性能目標,您可以創建附加的緩沖池;例如,您可以使一個緩沖池足夠大以存儲整個“熱”(或者說訪問非常頻繁的)表。當涉及到大的表時,某些 DB2 用戶將重要表的索引放入一個索引(BP_IX)緩沖池取得了很大成功。
太小的緩沖池會產生過多的、不必要的物理 I/O。太大的緩沖池使系統處在操作系統頁面調度的風險中并消耗不必要的 CPU 周期來管理過度分配的內存。正好合適的緩沖池大小就在“太小”和“太大”之間的某個平衡點上。適當的大小存在于回報將要開始減少的點上。如果您沒有使用工具來自動進行回報減少分析,那么您應該在不斷增加緩沖池大小上科學地測試緩沖池性能(命中率、I/O 時間和物理 I/O 讀取率),直到達到最佳的緩沖池大小。因為業務一直在變動和增長,所以應該定期重新評估“最佳大小”決策。
10. SQL 成本分析
一條糟糕的 SQL 語句會徹底破壞您的一整天。我不止一次地看到一個相對簡單的 SQL 語句搞糟了一個調整得很好的數據庫和機器。對于很多這些語句,天底下(或在文件中)沒有 DB2 UDB 配置參數能夠糾正因錯誤的 SQL 語句導致的高成本的情況。
更糟糕的是,DBA 常常受到種種束縛:不能更改 SQL(可能是因為它是應用程序供應商提供的,例如 SAP、 PeopleSoft或 Siebel)。這給 DBA 只留下三條路可走:
1. 更改或添加索引
2. 更改群集
3. 更改目錄統計信息
另外,如今健壯的應用程序由成千上萬條不同的 SQL 語句組成。這些語句執行的頻率隨應用程序的功能和日常的業務需要的不同而不同。SQL 語句的實際成本是它執行一次的成本乘以它執行的次數。
每個 DBA 所面臨的重大的任務是,識別具有最高“實際成本”的語句的挑戰,并且減少這些語句的成本。
通過本機 DB2 Explain 實用程序、一些第三方供應商提供的工具或 DB2 UDB SQL Event Monitor 數據,您可以計算出執行一次 SQL 語句所用的資源成本。但是語句執行頻率只能通過仔細和耗時地分析 DB2 UDB SQL Event Monitor 的數據來了解。
在研究 SQL 語句問題時,DBA 使用的標準流程是:
1. 創建一個 SQL Event Monitor,寫入文件:
$> db2 "create event monitor SQLCOST for statements write to ..."
2. 激活事件監視器(確保有充足的可用磁盤空間):
$> db2 "set event monitor SQLCOST state = 1"
3. 讓應用程序運行。
4. 取消激活事件監視器:
$> db2 "set event monitor SQLCOST state = 0"
5. 使用 DB2 提供的 db2evmon 工具來格式化 SQL Event Monitor 原始數據(根據 SQL 吞吐率可能需要數百兆字節的可用磁盤空間):
$> db2evmon -db DBNAME -evm SQLCOST
> sqltrace.txt
6. 瀏覽整個已格式化的文件,尋找顯著大的成本數(一個耗時的過程):
$> more sqltrace.txt
7. 對已格式化的文件進行更完整的分析,該文件試圖標識唯一的語句(獨立于文字值)、每個唯一語句的頻率(它出現的次數)和其總 CPU、排序以及其它資源成本的總計。如此徹底的分析在 30 分鐘的應用程序 SQL 活動樣本上可能要花一周或更多的時間。
要減少確定高成本 SQL 語句所花的時間,您可以考慮許多可用的信息來源:
從 技巧 4,務必要計算在每個事務中從每個表中讀取的行數。如果產生的數字看上去很大,那么 DBA 可以在 SQL Event Monitor 格式化輸出中搜索有關的表名稱(這將縮小搜索范圍而且節省一些時間),這樣也許能夠找出有問題的語句。從 技巧 3,務必計算每個表空間的異步讀取百分比和物理 I/O 讀取率。如果一個表空間的異步讀取百分比很高并遠遠超過平均的物理 I/O 讀取率,那么在此表空間中的一個或更多的表正在被掃描。查詢目錄并找出哪些表被分配到可疑的表空間(每個表空間分配一個表提供最佳性能檢測),然后在 SQL Event Monitor 格式化輸出中搜索這些表。這些也可能有助于縮小對高成本 SQL 語句的搜索范圍。 嘗試觀察應用程序執行的每條 SQL 語句的 DB2 Explain 信息。然而,我發現高頻率、低成本語句經常爭用機器容量和能力來提供期望的性能。 如果分析時間很短而且最大性能是關鍵的,那么請考慮使用供應商提供的工具(它們能夠快速自動化識別資源密集的 SQL 語句的過程)。 Database-GUYS Inc.的 SQL-GUY 工具提供精確、實時且均衡的 SQL 語句的成本等級分析。
繼續調節
最佳性能不僅需要排除高成本 SQL 語句,而且需要確保相應的物理基礎結構是適當的。當所有的調節旋鈕都設置得恰到好處、內存被有效地分配到池和堆而且 I/O 均勻地分配到各個磁盤時,才可得到最佳性能。雖然量度和調整需要時間,但是執行這 10 個建議的 DBA 將非常成功地滿足內部和外部的 DB2 客戶。因為電子商務的變化和增長,即使是管理得最好的數據庫也需要定期的微調。DBA 的工作永遠都做不完!
快速回顧最棒的 10 個技巧
對工作負載使用足夠的代理程序。
不允許 DB2 不必要地關閉和打開文件。
不允許長期的鎖等待。
確保數據庫的 TEMPSPACE 表空間的并行 I/O 能力。
保守地管理 DB2 排序內存并不要以大的 SORTHEAP 來掩蓋排序問題。
分析表的訪問活動并確定具有特別高的每個事務讀取行數或溢出數的表。
分析每個表空間的性能特性,并尋求改善讀取時間最慢、等待時間最長、物理 I/O 讀取率最高、命中率最差的表空間性能以及與所期望的不一致的訪問屬性。
創建多個緩沖池,有目的地將表空間分配到緩沖池以便于共享訪問屬性。
檢查 DB2 UDB SQL Event Monitor 信息以找到哪個 SQL 語句消耗計算資源最多并采取正確的措施。
四、冷備份與熱備份、雙機熱備與容錯
冷備份與熱備份
一、 冷備份
冷備份發生在數據庫已經正常關閉的情況下,當正常關閉時會提供給我們一個完整的數據庫。冷備份時將關鍵性文件拷貝到另外的位置的一種說法。對于備份Oracle信息而言,冷備份時最快和最安全的方法。冷備份的優點是:
1、 是非?焖俚膫浞莘椒ǎㄖ恍杩轿募
2、 容易歸檔(簡單拷貝即可)
3、 容易恢復到某個時間點上(只需將文件再拷貝回去)
4、 能與歸檔方法相結合,做數據庫“最佳狀態”的恢復。
5、 低度維護,高度安全。
但冷備份也有如下不足:
1、 單獨使用時,只能提供到“某一時間點上”的恢復。
2、 再實施備份的全過程中,數據庫必須要作備份而不能作其他工作。也就是說,在冷備份過程中,數據庫必須是關閉狀態。
3、 若磁盤空間有限,只能拷貝到磁帶等其他外部存儲設備上,速度會很慢。
4、 不能按表或按用戶恢復。
4如果可能的話(主要看效率),應將信息備份到磁盤上,然后啟動數據庫(使用戶可以工作)并將備份的信息拷貝到磁帶上(拷貝的同時,數據庫也可以工作)。冷備份中必須拷貝的文件包括:
1、 所有數據文件
2、 所有控制文件
3、所有聯機REDO LOG文件
4、 Init.ora文件(可選)
值得注意的使冷備份必須在數據庫關閉的情況下進行,當數據庫處于打開狀態時,執行數據庫文件系統備份是無效的。
下面是作冷備份的完整例子。
(1) 關閉數據庫
sqlplus /nolog
sql>connect /as sysdba
sql>shutdown normal;
(2) 用拷貝命令備份全部的時間文件、重做日志文件、控制文件、初始化參數文件
sql>cp
(3) 重啟Oracle數據庫
sql>startup
二、 熱備份
熱備份是在數據庫運行的情況下,采用archivelog mode方式備份數據庫的方法。所以,如果你有昨天夜里的一個冷備份而且又有今天的熱備份文件,在發生問題時,就可以利用這些資料恢復更多的信息。熱備份要求數據庫在Archivelog方式下操作,并需要大量的檔案空間。一旦數據庫運行在archivelog狀態下,就可以做備份了。熱備份的命令文件由三部分組成:
1. 數據文件一個表空間一個表空間的備份。
(1) 設置表空間為備份狀態
(2) 備份表空間的數據文件
(3) 恢復表空間為正常狀態
2. 備份歸檔log文件
(1) 臨時停止歸檔進程
(2) log下那些在archive rede log目標目錄中的文件
(3) 重新啟動archive進程
(4) 備份歸檔的redo log文件
3. 用alter database bachup controlfile命令來備份控制文件熱備份的優點是:
1. 可在表空間或數據庫文件級備份,備份的時間短。
2. 備份時數據庫仍可使用。
3. 可達到秒級恢復(恢復到某一時間點上)。
4. 可對幾乎所有數據庫實體做恢復
5. 恢復是快速的,在大多數情況下愛數據庫仍工作時恢復。
熱備份的不足是:
1. 不能出錯,否則后果嚴重
2. 若熱備份不成功,所得結果不可用于時間點的恢復
3. 因難于維護,所以要特別仔細小心,不允許“以失敗告終”。
雙機熱備的實現模式
雙機熱備有兩種實現模式,一種是基于共享的存儲設備的方式,另一種是沒有共享的存儲設備的方式,一般稱為純軟件方式。
基于存儲共享的雙機熱備是雙機熱備的最標準方案。
對于這種方式,采用兩臺(或多臺,參見:雙機與集群的異同)服務器,使用共享的存儲設備(磁盤陣列柜或存儲區域網SAN)。兩臺服務器可以采用互備、主從、并行等不同的方式。在工作過程中,兩臺服務器將以一個虛擬的IP地址對外提供服務,依工作方式的不同,將服務請求發送給其中一臺服務器承擔。同時,服務器通過心跳線(目前往往采用建立私有網絡的方式)偵測另一臺服務器的工作狀況。當一臺服務器出現故障時,另一臺服務器根據心跳偵測的情況做出判斷,并進行切換,接管服務。對于用戶而言,這一過程是全自動的,在很短時間內完成,從而對業務不會造成影響。由于使用共享的存儲設備,因此兩臺服務器使用的實際上是一樣的數據,由雙機或集群軟件對其進行管理。
對于純軟件的方式,則是通過鏡像軟件,將數據可以實時復制到另一臺服務器上,這樣同樣的數據就在兩臺服務器上各存在一份,如果一臺服務器出現故障,可以及時切換到另一臺服務器。
對于這種方式的深入分析,請參見:純軟件方式的雙機熱備方案深入分析
純軟件方式還有另外一種情況,即服務器只是提供應用服務,而并不保存數據(比如只進行某些計算,做為應用服務器使用)。這種情況下同樣也不需要使用共享的存儲設備,而可以直接使用雙機或集群軟件即可。但這種情況其實與鏡像軟件無關,只不過是標準的雙機熱備的一種小的變化。
雙機容錯的工作原理
1、雙機容錯的兩種方式
雙機容錯從工作原理上可以分為共享磁盤陣列柜方式和擴展鏡像純軟件方式兩種。這兩種方式的共同特點都是圍繞關鍵數據的可靠性,對操作系統、電源、CPU和主機主板進行容錯。
雙機共享磁盤陣列柜方式是以磁盤陣列柜為中心的雙機容錯方神機妙算,磁盤柜通過SCSI線連接到兩個系統上,并能被兩個系統所訪問。關鍵數據放在共享磁盤柜中,在正常運行時,控制友在主用系統上,當主用系統發生故障或主用系統檢查到某種故障后,系統控制權就切換到備用主機。主用系統修復后,主備角色互換,雙機系統進入正常工作模式。
雙機擴展鏡像酏軟件方式是純軟件方式的雙機容錯方案,兩個系統之間通過以太網連接,關鍵數據在兩個系統之間呈鏡像存在。在正常運行時,控制權在主用系統上,數據實時地鏡像到備用系統上。當主用系統發生故障或主用系統檢查到某種故障后,系統控制權切換到備用主機。由于采用以太網作為系統的數據鏈路,主用系統可不干擾備用系統工作,自動脫離并在一個孤立的環境中進行故障的診斷和維修,主用系統修復后,控制權需要切回到主用系統,數據需要從備用系統恢復到主用系統,這個工作在后臺自動完成,應用讀取數據仍從備用系統上進行而不會中斷。數據恢復完成后,雙機系統進入正常工作模式。
以上兩種雙機容錯的方式已經能很好地保證數據可靠,如果在主、備機上各運行一種應用還可實現相互備份。
2.共享磁盤陣列柜方式的工作原理
使用共享磁盤陣列柜方式的兩臺(或多臺)服務器的數據同時存放在一個磁盤陣列柜里,因此,不需要進行數據復制,只需在其中一臺服務器停機時將此服務器的工作轉移到另外一臺服務器,工作較為簡單。由于數據存儲在同一磁盤陣列柜里,一是磁盤陣列柜的數據捐贈 壞則數據全部丟失,有單點崩潰的可能性,而且由于服務器與磁盤陣列柜之間通常使用SCSI線連接,因此受到距離的了限制。
共享磁盤陣列車柜方式一般由監控系統與切換系統兩部分組成。
(1) 監控系統
A、SCSI偵測。共享磁盤陣列柜方式內部含有偵測心跳通信線路,偵測結果置于共享磁盤陣列柜上的一個5MB的小區,用于監控,此小區一般在機柜邏輯盤的起始段,對于某一臺服務器而言,將偵測信自己人以類似于記錄方式寫在該小區內,其中每一條記錄包括如下內容。
系統對本服務器的監測狀態信息
另一臺服務器是滯看到本服務器狀態信息,同時修改記錄區內容。
B、網絡偵測。當一臺服務器有問題或出現故障時,對等服務器的可調變心跳頻率不斷提高。在最小心跳時間內發現記錄內容沒有更新,即會調用網絡心跳偵測兩次確認系統狀態。當峽谷線心路都判斷系統故障時,共享磁盤陣列柜方式將故障服務器的交易業務在最小安全切換時間內切換到對等服務器上繼續運行。
C、切換系統
網絡服務器。雙服務器后臺,對于用戶一羰,由監控軟件共享磁盤陣列柜方式提供一個邏輯的IP地址,如192.192.192.1,任一用戶上網可以直接使用這一地址,當后臺其中一臺服務器出現故障時,另外一臺服務器會自己將其網卡的IP地址替換為192.192.192.1,這樣,用戶一端的網絡不會因為一臺服務器出現故障而斷掉。
數據庫服務。當其中一臺服務器出現故障時,另外一臺服務器會自動接管數據庫,同時啟動數據庫和應用程序,使用戶數據庫可以繼續操作,對用戶而言不受影響。
應用系統。當有一臺服務器出現故障時,另外一臺服務器會自動接管各類應用程序,同時啟動應用程序,使用戶可以繼續操作,對用戶而言不受影響。
3、擴展鏡像純軟件方式的工作原理
使用純軟件方式的軟件不需要共享磁盤陣列柜,它將數據存儲于各自服務器內,通過鏡相引擎將數據進行實時復制。當其中一臺服務器停機時,設定的服務器接管停機服務器的工作。由于數據存儲于不同服務器內,因此避免了單點崩潰的可能性,增加了數據的安全性。服務器之間通過網絡連接,所以服務器之間的連接受距離的限制較小。由于數據存儲在各自己服務器硬盤內,因此服務器之間有應用各不影響,提高了服務器正常使用時的效率。
4、熱備份
熱備份其實是計算機容錯技術的一個概念,是實現計算機系統高可用性的主要方式。熱備份采用磁盤鏡相技術,將運行著的計算機系統數據和應用數據同時保存在不同的硬盤上,鏡像在不同的磁盤上的數據在發生變化時同時刷新,從而保證數據一致性。當系統中的一個硬盤發生故障時,計算機可以使用鏡像數據,避免因系統單點故障(如硬盤故障)導致整個計算機系統無法運行,從而實現計算機系統的高可用性。
現在的計算機系統在系統建設時都普遍采用了熱備份方式,最典型的實現方式是雙機熱備份,即雙機容錯系統。雙機容錯系統在建設時選用兩臺同樣服務器,運行相同的操作系統、應用軟件(如數據庫軟件),兩臺服務器共享一個磁盤陣列,采用磁盤鏡像,將應用數據建立在磁盤陣列車上,實現雙機容錯。其中一臺服務器被指定為工作機,由它處理當前運行的業務,另一臺為備份服務器。一旦工作機發生故障,運行的業務請求將被人工(或自動)地切換到備份服務器,使運行著的業務不至于因為系統的單點故障中斷,實現系統的高可用性。
熱備份實現了計算機系統的高可用性,使一些對實時性要求很強的業務(如銀行信用卡業務)得以保障。然而,熱備份方式并不能解決所有計算機系統數據管理問題,舉一個最簡單的例子,如果操作人員誤刪除了一個文件,熱備系統為保證數據的一致性,會同時將這個文件的鏡像文件刪除,造成數據丟失。為防止有用的數據因系統故障和人為誤操作而損壞或丟失,實行數據存儲管理必不可少,數據存儲管理的核心是數據備份。
雙機容錯環境下Oracle數據庫的具體應用
目前許多建立和應用信息系統的企業,在系統應用不斷改進的同時,開始注意提高企業信息系統的可用性和可靠性。通過雙機容錯系統為企業提供系統高可用性保障是目前企業普遍采用的方法。
醫療機構工作性質的特殊性要求其信息系統7天×24小時不間斷運行,采用雙機容錯方案為系統提供了高可用解決方案。本文將對醫療信息系統的雙機容錯環境下Oracle數據庫應用做詳細介紹。
系統配置
該系統的硬件配置如下:
主數據庫服務器: 富士通Primergy MS-610服務器(雙Xeon 700MHz CPU,1GB內存)。
數據庫備份服務器: 富士通Team Server C870ie GP5C875(雙PentiumⅢ 700MHz CPU,1GB內存)。
容錯軟件: 天地公司的SLHA 3.0軟件包。
磁盤陣列: IQstore R1500(帶2個SCSI接口)。
線路連接: 2臺服務器用RS-232串口線和RJ-45網絡線相連(如圖1所示)。
軟件配置如下。
操作系統: Windows NT Server 4.0
服務器軟件配置: Windows NT 4.0 Service Pack 5、Inte.net Explorer 5.0、Microsoft Data Access Component 2.0,Oracle數據庫為7.3.3企業版。
雙機容錯的實現
1. 操作系統的安裝
我們用A機表示數據庫服務器,用B機表示備份數據庫服務器。首先在物理上將所需硬件設備連接好,分別在各自服務器上安裝Windows NT Server 4.0操作系統及補丁包等。然后,進入磁盤管理器,將磁盤陣列劃分為2個邏輯盤D和E,此時2臺服務器都可訪問磁盤陣列。
2.Oracle數據庫的安裝
先關閉B機,在A機上安裝Oracle數據庫,安裝路徑默認為D盤,歸檔日志放在E盤。安裝完畢后,將Oracle的3個服務(此處SID為ORCL,所以3個服務就是OracleServiceORCL、OracleStartORCL和OracleTNSlistener)的啟動方式改為手動并將此3個服務停止。注意: 改為手動的目的是為了讓這3個服務由雙機容錯軟件來啟動,而不是由操作系統啟動。
然后,關閉A機,啟動B機,格式化D盤,將剛剛由A機建立在磁盤陣列上的Oracle目錄也格式化掉; 在B機上安裝Oracle數據庫,安裝路徑默認為D盤,安裝完畢,同樣將Oracle的3個服務的啟動方式改為手動并停止3個服務。
雙機上安裝Oracle的實質就是將Oracle系統分別裝在2臺服務器上,而數據只存儲在磁盤陣列上。
3.雙機容錯軟件的安裝及雙機容錯環境的建立
雙機容錯軟件的安裝非常簡單,只需啟動A機和B機,在2臺服務器上分別安裝該軟件即可。建立雙機容錯環境是將磁盤陣列上的D盤和E盤以及Oracle 的3個服務交由雙機容錯軟件控制,并由雙機容錯軟件進行切換。
在雙機容錯軟件SLHA的"Configuration"選項中將數據庫服務器設為Active狀態,即平時正常工作狀態時,此時數據庫服務器工作,備份服務器等待。當A機Active時,只有A機可以訪問磁盤陣列,B機不能訪問磁盤陣列。此時,Oracle數據庫服務器實際上是A機,A機的IP地址就是Active IP Address,同時A機的主機名為Active Host Name; 當A機因故不能工作時,A機的狀態會被"心跳線"偵測到,這時B機開始切換到Active狀態,接管磁盤陣列,此時的Oracle數據庫服務器改為B機,B機的IP地址就是Active IP Address,同時B機的主機名為Active Host Name。上述操作均由系統自動完成,實踐證明切換所需的時間很快,對客戶端的影響很小。
需要注意的問題
1.當在A機安裝完Oracle數據庫后在B機安裝Oracle數據庫時,一定要先將磁盤陣列D盤格式化,而不是只將D盤中已由A機安裝的Oracle數據庫刪除,否則可能會出現意想不到的錯誤,例如Oracle偵聽服務失敗等;
2.最終安裝好Oracle數據庫后,要對D:\Oracle\Orant\network\Admin\ Listener.ora文件進行修改,其中Server名稱一定要改為Active host name Alias,如不進行修改將使客戶端的Oracle數據庫用戶無法連接到Oracle數據庫中。
3.在Hosts文件中增加一條記錄,使Active IP Address和Active Host Name相互對應,這樣系統就會自動起到解析作用。Hosts文件位于c:\Winnt\ system32\drivers\etc目錄下。
4.要注意不到萬不得已,不要強行切換,避免產生數據錯誤。如必須對雙機進行切換,可先進入Svrmgr Oracle服務器控制臺,用Shutdown命令關閉Oracle數據庫,再進行切換。
雙機容錯的原理
Oracle數據庫安裝在磁盤陣列上(即圖2中Public Drives),2臺服務器都可以訪問它,但不能同時訪問。Oracle Server for NT主要提供3個服務:OracleServiceSID、OracleStartSID和OracleTNSlistener。在數據庫服務器正常工作時,由數據庫服務器控制磁盤陣列柜,此時只有該服務器可以訪問磁盤陣列,該服務器上的Oracle服務處于啟動(Active)狀態,此時該服務器就扮演圖2中Active Server的角色,備份服務器處于等待(Standby)狀態,即圖2中Backup Server。
當數據庫服務器發生故障不能工作時,雙機容錯系統會檢測到數據庫服務器的狀態,從而使備份服務器自動激活,接管磁盤陣列并自動啟動Oracle的3個服務,而對于客戶端來說,只經歷一個短暫的服務器重啟過程,訪問的數據仍是磁盤陣列中的數據。
注意: 是雙機容錯軟件而不是操作系統來控制Oracle 的啟動和停止,即由雙機容錯軟件來控制這3個Oracle服務的啟動和停止,實現Oracle數據庫在雙機之間的切換
以下是對Oracle數據庫編程的總結 ,現在有很多的常用的數據庫,其中包括Oracle, MS SQL Server, Sybase, Informix, MySQL, DB2, Interbase / Firebird, PostgreSQL, SQLite, SAP/DB, TimesTen, MS ACCESS等等。
數據庫編程是對數據庫的創建、讀寫等一列的操作。
數據庫編程分為數據庫客戶端編程與數據庫服務器端編程。數據庫客戶端編程主要使用ODBC API、ADO、ADO.NET、OCI、OTL等方法;數據庫服務端編程主要使用OLE DB等方法。Oracle數據庫編程需要掌握一些訪問數據庫技術方法,還需要注意怎么設計高效的數據庫、數據庫管理與運行的優化、數據庫語句的優化。
一、訪問數據庫技術方法
數據庫編程分為數據庫客戶端編程與數據庫服務器端編程。數據庫客戶端編程主要使用ODBC API、ADO、ADO.NET、OCI、OTL等方法;數據庫服務端編程主要使用OLE DB等方法。
1、幾種是數據庫訪問方法比較
ODBC API是一種適合數據庫底層開發的編程方法,ODBC API提供大量對數據源的操作,ODBC API能夠靈活地操作游標,支持各種幫定選項,在所有ODBC相關編程中,API編程具有最高的執行速度。
DAO提供了很好的Oracle數據庫編程的對象模型.但是,對數據庫的所有調用以及輸出的數據都必須通過Access/Jet數據庫引擎,這對于使用數據庫應用程序,是嚴重的瓶頸。
OLE DB提供了COM接口,與傳統的數據庫接口相比,有更好的健壯性和靈活性,具有很強的錯誤處理能力,能夠同非關系數據源進行通信。
ADO最主要的優點在于易于使用、速度快、內存支出少和磁盤遺跡小。
ADO.NET 是利用數據集的概念將數據庫數據讀入內存中,然后在內存中對數據進行操作,最后將數據集數據回寫到源數據庫中。
OTL 是 Oracle, Odbc and DB2-CLI Template Library 的縮寫,是一個C++編譯中操控關系數據庫的模板庫, OTL中直接操作Oracle主要是通過Oracle提供的OCI接口進行,進行操作DB2數據庫則是通過CLI接口來進行,至于MS的數據庫和其它一些數據庫,則OTL只提供了ODBC來操作的方式。
當然Oracle和DB2也可以由OTL間接使用ODBC的方式來進行操縱。具有以下優點:跨平臺;運行效率高,與C語言直接調用API相當;開發效率高,起碼比ADO.net使用起來更簡單,更簡潔;部署容易,不需要ADO組件,不需要.net framework 等。
2、VC數據庫編程幾種方法
VC數據庫編程幾種方法,包括ODBC連接、MFC ODBC連接、DAO連接、OLE DB、OLE DB Templates連接、ADO、Oracle專用方法(OCI(Oracle Call Interface)訪問、Oracle Object OLE C++ Class Library )。
<1.>通用方法
1. ODBC連接
ODBC(Open DataBase Connectivity)是MSOA的一部分,是一個標準數據庫接口。它提供對關系數據庫訪問的統一接口,實現對異構數據源的一致訪問。
ODBC數據訪問由以下部分組成:
<1>句柄(Handles):ODBC使用句柄來標識ODBC環境、連接、語句和描述器.
<2>緩存區(Buffers):
<3>數據類型(Data types)
<4>一致性級別(Conformance levels)
用ODBC設計客戶端的一般步驟:
<1>分配ODBC環境
<2>分配連接句柄
<3>連接數據源
<4>構造和執行SQL語句
<5>獲得查詢結果
<6>斷開數據源的連接
<7>釋放ODBC環境
ODBC API是一種適合數據庫底層開發的編程方法,ODBC API提供大量對數據源的操作,ODBC API能夠靈活地操作游標,支持各種幫定選項,在所有ODBC相關編程中,API編程具有最高的執行速度.因此,ODBC API編程屬于底層編程。
2. MFC ODBC連接
MFC ODBC是MFC對ODBC進行的封裝,以簡化對ODBC API的 調用,從而實現面向對象的Oracle數據庫編程接口.
MFC ODBC的封裝主要開發了CDatabase類和CRecordSet類
(1) CDatabase類
CDatabase類用于應用程序建立同數據源的連接。CDatabase類中包含一個m_hdbc變量,它代表了數據源的連接句柄。如果要建立CDatabase類的實例,應先調用該類的構造函數,再調用Open函數,通過調用,初始化環境變量,并執行與數據源的連接。在通過Close函數關閉數據源。
CDatabase類提供了對數據庫進行操作的函數及事務操作。
(2) CRecordSet類
CRecordSet類定義了從數據庫接收或者發送數據到數據庫的成員變量,以實現對數據集的數據操作。
CRecordSet類的成員變量m_hstmt代表了定義該記錄集的SQL語句句柄,m_nFields為記錄集中字段的個數,m_nParams為記錄集所使用的參數個數。
CRecordSet的記錄集通過CDatabase實例的指針實現同數據源的連接,即CRecordSet的成員變量m_pDatabase.
MFC ODBC編程更適合于界面型數據庫應用程序的開發,但由于CDatabase類和CRecordSet類提供的數據庫操作函數有限,支持的游標類型也有限,限制了高效的數據庫開發。在編程層次上屬于高級編程。
文章來源于領測軟件測試網 http://www.kjueaiud.com/