熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Oracle >> 正文

復雜應用環境監控ORACLE數據庫性能

2022-06-13   來源: Oracle 

  前言:
  
    在單一的應用環境或業務相對簡單的系統下 系統性能問題 瓶頸所在往往是不言自明 解決問題的前提定位問題是比較容易解決的 但在一個復雜的應用環境下 各應用系統對系統資源往往是一種共享和競爭的關系 而且應用系統之間也可能存在著共生或制約的關系 資源利益的均衡往往是此消彼長 而這種環境下的應用系統一旦出現資源競爭 系統的瓶頸往往難以斷定 甚至會發生不同應用設計人員之間互相推诿責任的扯皮現象 本文僅就此問題對Linux平台下各應用系統對ORACLE數據庫的使用情況作一探討 ORACLE數據庫的TUNING不是一個可以一言以蔽的主題 本文無意概全 內容僅涉及問題的定位及各應用對數據庫資源的共享與競爭問題
  
  本文試驗及問題取證的環境:
  
  RedHat Web server(Apache+PHP)+Client/Server(Pro*C)之Server端
  
  RedHat + Oracle
  
  RedHat Web server(Apache+PHP) + Oracle
  
    為方便問題的討論 應用系統已做簡化 競爭方僅包括一個Pro*C的daemon程序作為C/S模式的服務端 和由Apache+PHP所支持的WEB網站業務
  
   單個SQL語句的處理
  
    首先 最簡單的情況莫過於單個SQL語句的分析 SQL語句的優化也是數據庫優化的一個最直接最立竿見影的因素 SQL語句的性能監控從監控工具來說大致可分為由高級語言提供和由ORACLE本身提供 高級語言以典型的應用C 語言和WEB開發語言PHP為例 C語言中可以用gettimeofday函數來在某一數據庫操作之前和之後分別獲取一個時間值 將兩個時間值之差做為衡量該數據庫操作的效率 在PHP中 也可以用gettimeofday 操作方法當然與C語言中有所不同 當然 PHP中也有其它一些函數可以達到同樣的時間精度 關於時間精度的考慮 不能簡單以大小衡量微秒級的時間數值 因為時鐘中斷的時間間隔從根本上決定了時間計算所能達到的精度 此外 操作系統本身對進程的時間片分配 及進程切換的開銷等因素也在一定程度上影響時間數據的意義 所以 以下時間的計算最理想的情況是對同一操作在盡可能避免緩存的情況下進行多次的循環操作 取總的時間值加以平均 從而得到比較接近真實情況的時間值
  
  C語言的例子:
  
  
  ==========================================================
  #define TV_START
  #define TV_END
  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;;
  how_long(TV_END time_consume);
  puts(time_consume);
  }
  int how_long(int cmd char *res)
  /* return value: error sucess res: bytes is enough */
  {
  static struct timeval before after;
  if(cmd == TV_START) {
  gettimeofday(&before NULL);
  return ;
  } else if(cmd == TV_END) {
  gettimeofday(&after NULL);
  if(res) {
  if(aftertv_usec > beforetv_usec) {
  sprintf(res %ld %ld aftertv_sec beforetv_sec
  aftertv_usec beforetv_usec);
  } else {
  sprintf(res %ld %ld
  aftertv_sec beforetv_sec
   + aftertv_usec beforetv_usec);
  }
  }
  return ;
  } else {
  return ;
  }
  }
  ==========================================================
  
  下面是一個PHP的例子(為簡化起見 程序的錯誤檢查被忽略)
  
  ==========================================================
  include /how_longinc;
  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 用戶ID: $id 該操作消耗時間:$timestr
  ;
  ?>
  其中how_long函數的PHP版本如下:
  #作者:
  #當前維護人:
  #創建日期: ::
  #目的 在一個操作之前或之後調用該函數的不同版本 將得到一個記載了該操作
  #耗費時間的字符串 該函數本身的開銷不計入其中
  define(TV_START );
  define(TV_END );
  function how_long($operation &$str)
  #返回值: 成功 傳遞了非法的參數
  {
  global $before_SQL $after_SQL;
  if($operation == TV_START) {
  $before_SQL = gettimeofday();
  return ;
  } else if($operation == TV_END) {
  $after_SQL = gettimeofday();
  if($before_SQL[usec] > $after_SQL[usec]) {
  $str = ($after_SQL[sec] $before_SQL[sec] )
  ($after_SQL[usec] + * $before_SQL[usec])微秒;
  } else {
  $str = ($after_SQL[sec] $before_SQL[sec])
  ($after_SQL[usec]$before_SQL[usec])微秒;
  }
  } else {
  return ;
  }
  }
  ?>
  ==========================================================
  
    上面的數據庫操作開銷的計算僅限於對時間消耗的計算 對同時使用同一數據庫的其它應用軟件的影響 對磁盤操作的頻繁程度 數據庫操作所采取的具體策略等等因素 都未考慮在內 高級語言也不可能提供這樣的參考數據 而數據庫本身提供的監測手段彌補了這一不足 最簡單的操作控制台:sqlplus
  
  SQL> set timing on
  
  將為每次執行的數據庫操作進行計時 精度為/ 筆者對該功能的使用中發現其時間的計算也有一定的偏差 而且時間偏差很大 嚴格說來 已不屬於誤差的范圍 該歸錯誤了 下面是一個例子中得到的數據:
  
  
  [bash$] cat tmpsql
  set timing on
  host date;
  select count(*) from users;
  host date;
  SQL> @tmpsql
  Wed Dec :: CST
  
  COUNT(*)
  
  
  Elapsed: ::
  Wed Dec :: CST
  
  從系統的時間差來看秒左右 但ORACLE卻報告了秒!
  如果說ORACLE工具在時間計算上太差強人意的話 在SQL語句的執行方案上可算是對SQL語句如何執行的最權威的诠釋了 解讀這樣的信息需要對ORACLE內部對SQL 操作的過程有一定了解 下面是該功能的一樣典型示例:
  
  SQL> set autotrace on
  SQL> select count(*) from users;
  COUNT(*)
  
  
  Execution Plan
  
   SELECT STATEMENT Optimizer=CHOOSE (Cost= Card=)
   SORT (AGGREGATE)
   INDEX (FAST FULL SCAN) OF USER_BASEINFO$NAME (UNIQUE)
  (Cost= Card=)
  Statistics
  
   recursive calls
   db block gets
   consistent gets
   physical reads
   redo size
   bytes sent via SQL*Net to client
   bytes received via SQL*Net from client
   SQL*Net roundtrips to/from client
   sorts (memory)
   sorts (disk)
   rows processed
  
    Execution Plan下的信息顯示ORACLE制定了一個什麼樣的計劃來完成SQL操作的SQL語言是一種GL語言 其特點是告訴系統做什麼 而不提供如何做的信息 當然 最終的具體工作總得有人做的 只是由數據庫自動制定而不是程序員人為指定一個具體的操作步驟 制作這個步驟當然要有所依據 ORACLE有兩個基本原則來決定如何優化: costbased(基於開銷的優化)和rulebased(基於規則的優化) 基於開銷的優化的工作方式依賴於數據庫對SQL語句所操作的數據對象(可簡單認為就是表)的數據特征的統計特性進行收集和分析 收集分析的工作由DBA來定期執行 時間間隔依數據變化頻率而定 以保持統計數據一定的准確性 具體操作請參照 analyze 語句 Oracle准備在將來的版本中取消對基於開銷的優化方案的支持 因為這種方案需要大量的數據收集與分析工作 且總會有一定的誤差 這造成最終的執行方案往往不是最優的
    基於規則的優化則是依據一些數據操作效率的規則進行選擇 優化的核心在於效率 時間上盡可能短 空間上盡可能少進行IO 操作 兩種優化方案都絕非十全十美 ORACLE雖將其稱為優化方案 筆者的觀察結果表明 ORACLE制定出一個不是最優或錯誤的執行方案也是完全可能的 以上為例 Oracle的優化策略
From:http://tw.wingwit.com/Article/program/Oracle/201311/16785.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.