時(shí)間:2015-06-28 00:00:00 來(lái)源:IT貓撲網(wǎng) 作者:網(wǎng)管聯(lián)盟 我要評(píng)論(0)
在單一的應(yīng)用環(huán)境或業(yè)務(wù)相對(duì)簡(jiǎn)單的系統(tǒng)下,系統(tǒng)性能問(wèn)題,瓶頸所在往往是不言自明,解決問(wèn)題的前提——定位問(wèn)題是比較容易解決的,但在一個(gè)復(fù)雜的應(yīng)用環(huán)境下,各應(yīng)用系統(tǒng)對(duì)系統(tǒng)資源往往是一種共享和競(jìng)爭(zhēng)的關(guān)系,而且應(yīng)用系統(tǒng)之間也可能存在著共生或制約的關(guān)系,資源利益的均衡往往是此消彼長(zhǎng),而這種環(huán)境下的應(yīng)用系統(tǒng)一旦出現(xiàn)資源競(jìng)爭(zhēng),系統(tǒng)的瓶頸往往難以斷定,甚至?xí)l(fā)生不同應(yīng)用設(shè)計(jì)人員之間互相推諉責(zé)任的扯皮現(xiàn)象,本文僅就此問(wèn)題對(duì)Linux平臺(tái)下各應(yīng)用系統(tǒng)對(duì)ORACLE數(shù)據(jù)庫(kù)的使用情況作一探討,ORACLE數(shù)據(jù)庫(kù)的TUNING不是一個(gè)可以一言以蔽的主題,本文無(wú)意概全,內(nèi)容僅涉及問(wèn)題的定位及各應(yīng)用對(duì)數(shù)據(jù)庫(kù)資源的共享與競(jìng)爭(zhēng)問(wèn)題。
本文試驗(yàn)及問(wèn)題取證的環(huán)境:
RedHat6.1 Web server(Apache1.3.9+PHP4.0)+Client/Server(Pro*C)之Server端
RedHat6.2 + Oracle8.1.6.1.0
RedHat7.1 Web server(Apache1.3.20+PHP4.06) + Oracle8.1.7.0.0
為方便問(wèn)題的討論,應(yīng)用系統(tǒng)已做簡(jiǎn)化,競(jìng)爭(zhēng)方僅包括一個(gè)Pro*C的daemon程序作為C/S模式的服務(wù)端,和由Apache+PHP所支持的WEB網(wǎng)站業(yè)務(wù)。
1. 單個(gè)SQL語(yǔ)句的處理
首先,最簡(jiǎn)單的情況莫過(guò)于單個(gè)SQL語(yǔ)句的分析,SQL語(yǔ)句的優(yōu)化也是數(shù)據(jù)庫(kù)優(yōu)化的一個(gè)最直接最立竿見(jiàn)影的因素。SQL語(yǔ)句的性能監(jiān)控從監(jiān)控工具來(lái)說(shuō)大致可分為由高級(jí)語(yǔ)言提供和由ORACLE本身提供,高級(jí)語(yǔ)言以典型的應(yīng)用C 語(yǔ)言和WEB開(kāi)發(fā)語(yǔ)言PHP為例,C語(yǔ)言中可以用gettimeofday函數(shù)來(lái)在某一數(shù)據(jù)庫(kù)操作之前和之后分別獲取一個(gè)時(shí)間值,將兩個(gè)時(shí)間值之差做為衡量該數(shù)據(jù)庫(kù)操作的效率,在PHP中,也可以用gettimeofday, 操作方法當(dāng)然與C語(yǔ)言中有所不同. 當(dāng)然, PHP中也有其它一些函數(shù)可以達(dá)到同樣的時(shí)間精度, 關(guān)于時(shí)間精度的考慮, 不能簡(jiǎn)單以大小衡量微秒級(jí)的時(shí)間數(shù)值, 因?yàn)闀r(shí)鐘中斷的時(shí)間間隔從根本上決定了時(shí)間計(jì)算所能達(dá)到的精度, 此外, 操作系統(tǒng)本身對(duì)進(jìn)程的時(shí)間片分配, 及進(jìn)程切換的開(kāi)銷(xiāo)等因素也在一定程度上影響時(shí)間數(shù)據(jù)的意義. 所以, 以下時(shí)間的計(jì)算最理想的情況是對(duì)同一操作在盡可能避免緩存的情況下進(jìn)行多次的循環(huán)操作, 取總的時(shí)間值加以平均, 從而得到比較接近真實(shí)情況的時(shí)間值。
?
C語(yǔ)言的例子:
?
========================================================== #define TV_START 0 #define TV_END 1 int how_long(int cmd, char *res); struct CMD_TIME{ int times; /* times occured within specified package number */ struct timeval time; /* total time consumed by the cmd */ };void foo() { int id; how_long(TV_START, NULL); EXEC SQL WHENEVER SQLERROR CONTINUE; EXEC SQL WHENEVER NOT FOUND CONTINUE; EXEC SQL select user_id into :id from users where name='slimzhao';2; how_long(TV_END, time_consume); puts(time_consume); } int how_long(int cmd, char *res) /* return value: -1 error, 0 sucess , res: 20 bytes is enough */ { static struct timeval before, after; if(cmd == TV_START) { gettimeofday(&before, NULL); return 0; } else if(cmd == TV_END) { gettimeofday(&after, NULL); if(res) { if(after.tv_usec > before.tv_usec) { sprintf(res, "%ld %ld", after.tv_sec - before.tv_sec, after.tv_usec - before.tv_usec); } else { sprintf(res, "%ld %ld", after.tv_sec - before.tv_sec - 1, 1000000 + after.tv_usec - before.tv_usec); } } return 0; } else { return -1; } } ==========================================================
下面是一個(gè)PHP的例子(為簡(jiǎn)化起見(jiàn), 程序的錯(cuò)誤檢查被忽略)
?
========================================================== /how_long.inc"; how_long(TV_START, $timestr); $conn = OCILogon("username", "password", "dblink"); $stmt = OCIParse($conn, "select ID from users where name='slimzhao'"); OCIDefineByName($stmt, ID, $id); OCIExecute($stmt); OCIFetch($stmt); OCIFreeStatement($stmt); OCILogoff($conn); how_long(TV_END, $timestr); echo "用戶(hù)ID: $id , 該操作消耗時(shí)間:$timestr
"; ?> 其中how_long函數(shù)的PHP版本如下: $after_SQL["usec"]) { $str = ($after_SQL["sec"] - $before_SQL["sec"] - 1)."秒". ($after_SQL["usec"] + 1000*1000 -$before_SQL["usec"])."微秒"; } else { $str = ($after_SQL["sec"] - $before_SQL["sec"])."秒". ($after_SQL["usec"]-$before_SQL["usec"])."微秒"; } } else { return -1; } } ?> ==========================================================
上面的數(shù)據(jù)庫(kù)操作開(kāi)銷(xiāo)的計(jì)算僅限于對(duì)時(shí)間消耗的計(jì)算, 對(duì)同時(shí)使用同一數(shù)據(jù)庫(kù)的其它應(yīng)用軟件的影響, 對(duì)磁盤(pán)操作的頻繁程度, 數(shù)據(jù)庫(kù)操作所采取的具體策略等等因素, 都未考慮在內(nèi), 高級(jí)語(yǔ)言也不可能提供這樣的參考數(shù)據(jù). 而數(shù)據(jù)庫(kù)本身提供的監(jiān)測(cè)手段彌補(bǔ)了這一不足. 最簡(jiǎn)單的操作控制臺(tái):sqlplus
SQL> set timing on
將為每次執(zhí)行的數(shù)據(jù)庫(kù)操作進(jìn)行計(jì)時(shí), 精度為1/100秒, 筆者對(duì)該功能的使用中發(fā)現(xiàn)其時(shí)間的計(jì)算也有一定的偏差. 而且時(shí)間偏差很大, 嚴(yán)格說(shuō)來(lái), 已不屬于誤差的范圍, 該歸錯(cuò)誤了, 下面是一個(gè)例子中得到的數(shù)據(jù):
?
[bash$] cat tmp.sql set timing on host date; select count(*) from users; host date;SQL> @tmp.sql Wed Dec 5 00:21:01 CST 2001
COUNT(*) ---------- 1243807
Elapsed: 00:00:06.16 Wed Dec 5 00:21:05 CST 2001
從系統(tǒng)的時(shí)間差來(lái)看, 為4秒左右, 但ORACLE卻報(bào)告了6.16秒!
如果說(shuō)ORACLE工具在時(shí)間計(jì)算上太差強(qiáng)人意的話(huà), 在SQL語(yǔ)句的執(zhí)行方案上可算是對(duì)SQL語(yǔ)句如何執(zhí)行的最權(quán)威的詮釋了. 解讀這樣的信息需要對(duì)ORACLE內(nèi)部對(duì)SQL 操作的過(guò)程有一定了解, 下面是該功能的一樣典型示例:
SQL> set autotrace on SQL> select count(*) from users; COUNT(*) ---------- 1243807Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=CHOOSE (Cost=4 Card=1) 1 0 SORT (AGGREGATE) 2 1 INDEX (FAST FULL SCAN) OF 'USER_BASEINFO$NAME' (UNIQUE) (Cost=4 Card=1244840)
Statistics ---------------------------------------------------------- 0 recursive calls 4 db block gets 3032 consistent gets 3033 physical reads 0 redo size 370 bytes sent via SQL*Net to client 424 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed
Execution Plan下的信息顯示ORACLE制定了一個(gè)什么樣的計(jì)劃來(lái)完成SQL操作的,SQL語(yǔ)言是一種4GL語(yǔ)言, 其特點(diǎn)是告訴系統(tǒng)做什么, 而不提供如何做的信息. 當(dāng)然, 最終的具體工作總得有人做的, 只是由數(shù)據(jù)庫(kù)自動(dòng)制定而不是程序員人為指定一個(gè)具體的操作步驟, 制作這個(gè)步驟當(dāng)然要有所依據(jù), ORACLE有兩個(gè)基本原則來(lái)決定如何優(yōu)化: cost-based(基于開(kāi)銷(xiāo)的優(yōu)化)和rule-based(基于規(guī)則的優(yōu)化). 基于開(kāi)銷(xiāo)的優(yōu)化的工作方式依賴(lài)于數(shù)據(jù)庫(kù)對(duì)SQL語(yǔ)句所操作的數(shù)據(jù)對(duì)象(可簡(jiǎn)單認(rèn)為就是表)的數(shù)據(jù)特征的統(tǒng)計(jì)特性進(jìn)行收集和分析. 收集分析的工作由DBA來(lái)定期執(zhí)行 , 時(shí)間間隔依數(shù)據(jù)變化頻率而定, 以保持統(tǒng)計(jì)數(shù)據(jù)一定的準(zhǔn)確性, 具體操作請(qǐng)參照 analyze 語(yǔ)句. Oracle準(zhǔn)備在將來(lái)的版本中取消對(duì)基于開(kāi)銷(xiāo)的優(yōu)化方案的支持, 因?yàn)檫@種方案需要大量的數(shù)據(jù)收集與分析工作, 且總會(huì)有一定的誤差, 這造成最終的執(zhí)行方案往往不是最優(yōu)的.
基于規(guī)則的優(yōu)化則是依據(jù)一些數(shù)據(jù)操作效率的規(guī)則進(jìn)行選擇, 優(yōu)化的核心在于效率, 時(shí)間上盡可能短, 空間上盡可能少進(jìn)行IO 操作. 兩種優(yōu)化方案都絕非十全十美, ORACLE雖將其稱(chēng)為優(yōu)化方案, 筆者的觀(guān)察結(jié)果表明, ORACLE制定出一個(gè)不是最優(yōu)或錯(cuò)誤的執(zhí)行方案也是完全可能的. 以上為例, Oracle的優(yōu)化策略是Choose, 所謂Choose就是cost-based或rule-based , 讓ORACLE自
關(guān)鍵詞標(biāo)簽:性能,監(jiān)控,環(huán)境,應(yīng)用,
相關(guān)閱讀 LAMP 架構(gòu)服務(wù)器性能優(yōu)化建議 針對(duì)Win2000優(yōu)化Web服務(wù)器性能 Oracle性能究極優(yōu)化 Oracle數(shù)據(jù)庫(kù)性能優(yōu)化技術(shù) FTP空間不足 Windows 系統(tǒng)性能監(jiān)控來(lái)報(bào)警 影響SQL server性能的關(guān)鍵
熱門(mén)文章 Oracle中使用alter table來(lái)增加,刪除,修改列的語(yǔ)法 oracle中使用SQL語(yǔ)句修改字段類(lèi)型-oracle修改SQL語(yǔ)句案例 誤刪Oracle數(shù)據(jù)庫(kù)實(shí)例的控制文件 為UNIX服務(wù)器設(shè)置Oracle全文檢索
時(shí)間:2022-05-10 12:07:13
時(shí)間:2021-05-21 14:24:10
時(shí)間:2020-11-05 15:35:02
時(shí)間:2020-07-17 13:09:02
時(shí)間:2020-02-24 16:08:56
時(shí)間:2018-12-26 18:50:37
人氣排行 oracle中使用SQL語(yǔ)句修改字段類(lèi)型-oracle修改SQL語(yǔ)句案例 Oracle中使用alter table來(lái)增加,刪除,修改列的語(yǔ)法 ORACLE SQL 判斷字符串是否為數(shù)字的語(yǔ)句 ORACLE和SQL語(yǔ)法區(qū)別歸納(1) oracle grant 授權(quán)語(yǔ)句 ORACLE修改IP地址后如何能夠使用 如何加速Oracle大批量數(shù)據(jù)處理 Oracle刪除表的幾種方法