2017-05-30 42 views
-4

對於比較OCCI(Oracle C++調用接口)和舊的JDBC的性能測試,我感到非常驚訝。JDBC比OCCI顯着更快。我應該感到驚訝嗎?

下面是代碼:

#include <iostream> 
#include <cstdlib> 
#include <occi.h> 

using namespace oracle::occi; 
using namespace std; 

const string username = "system"; 
const string password = "******"; 
const string url  = "(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=XE)))"; 
const string sql  = "select * from CREDITO.movtos_cuentas"; 

int main(int argc, char** argv) { 

    cout << "Oracle Connectivity" << endl; 

    Environment *env = Environment::createEnvironment(Environment::DEFAULT); 
    Connection *conn = env->createConnection(username, password, url); 
    Statement *stm = conn->createStatement(sql); 
    ResultSet *rs = stm->executeQuery(); 

    unsigned long count = 0; 

    while (rs->next()) { 
     count++; 
    } 

    stm->closeResultSet(rs); 
    conn->terminateStatement(stm); 
    env->terminateConnection(conn); 
    Environment::terminateEnvironment(env); 

    cout << "Registros na CREDITO.MOVTOS_CUENTAS: " << count << endl; 

    return 0; 
} 

這裏是Java代碼:

package oraconnect.jdbc; 

import java.sql.Connection; 
import java.sql.DriverManager; 
import java.sql.ResultSet; 
import java.sql.SQLException; 
import java.sql.Statement; 

public class OraconnectJdbc { 

    public static void main(String[] args) { 
     Connection conn = null; 
     Statement stm = null; 
     ResultSet rs = null; 

     try { 
      Class.forName("oracle.jdbc.driver.OracleDriver"); 
      conn = DriverManager.getConnection(
        "jdbc:oracle:thin:@127.0.0.1:1521:xe", "system", "******"); 
      stm = conn.createStatement(); 
      rs = stm.executeQuery("select * from CREDITO.movtos_cuentas"); 
      long count = 0; 
      while (rs.next()) { 
       count++; 
      } 

      System.out.printf("Registros na CREDITO.MOVTOS_CUENTAS: %d\n", count); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } finally { 
      if (rs != null) { 
       try { 
        rs.close(); 
       } catch (SQLException e) { 
        //Ignore 
       } 
      } 
      if (stm != null) { 
       try { 
        stm.close(); 
       } catch (SQLException e) { 
        //Ignore 
       } 
      } 
      if (conn != null) { 
       try { 
        conn.close(); 
       } catch (SQLException e) { 
        //Ignore 
       } 
      } 
     } 
    } 
} 

執行:

C++版本

time LD_LIBRARY_PATH=/home/eduardo/Private/Oracle/instantclient_11_2/. ./oraconnect 

Java版本

time java -jar oraconnect-jdbc.jar -cp lib/oracle-driver-11.2.0.3.jar 

C++結果:

real 1m29.392s 
user 0m32.788s 
sys  0m20.812s 

Java結果:

real 0m28.404s 
user 0m12.076s 
sys  0m4.236s 

結論:

Java是顯著快於C++

我不知道我已經做出了錯誤或使用一些不好的實踐e與C++版本。任何人都可以幫助我理解這個結果嗎?

+3

他發佈了一個問題,你不能相信接下來會發生什麼! –

+0

NathanOliver,結果已發佈。 – filosofisto

+0

結論 - 你跑第二的速度更快,因爲一堆數據已經從磁盤中提取出來,並且坐在SGA中。 –

回答

0

當您測量時間時,差異是有效的。 如果你想了解,爲什麼他們不同,你需要把整個時間分成一些部分,看看他們是相似還是不同。並瞭解差異的原因。 這可以通過許多不同的方法完成,例如跟蹤或採樣二進制文件上的調用堆棧,在網絡層或其他許多方法上執行tcpdump。 一個非常方便的方法是在Oracle數據庫中啓用SQL_TRACE - 您可以在其中花費大量時間。有關啓用SQL_TRACE的方法的好介紹是https://oracle-base.com/articles/misc/sql-trace-10046-trcsess-and-tkprof。 這些跟蹤文件包含大量數據,很難被讀取,特別是在開始時。有幾種工具(大多數稱爲「Profiler」)可用於處理這些文件。主導產品(從我的角度來看)是Method-R Profiler - 但由於這需要花錢,您可以嘗試使用https://antognini.ch/2017/03/tvdxtat-4-0-beta-11/

沒有任何進一步的信息,沒有人可以告訴性能差異的原因是什麼。但是通過可用的工具,您可以識別它們。那麼你要麼比另一個更快地接受一個解決方案,要麼修復它。

編輯: 我會提供了一個例子: 除了許多其他原因,存在的默認行爲的差異: OCCI一次獲取2行: Accessing Oracle Database Using C++

默認情況下,預取開啓,並且數據庫始終提取額外的一行 。

但是JDBC有一個結果集的10: Database JDBC Developer's Guide - Result Set

默認情況下,當Oracle JDBC運行一個查詢,它檢索結果從數據庫遊標中設定的10行 。

因此可能發生的情況是,使用OCCI的網絡往返時間比使用jdbc多5倍。

這僅僅是一個例子 - 它可能是你觀察與否的原因。可以肯定的是,你需要衡量,而不是猜測或要求猜測。

+0

謝謝馬丁,我同意爲了好理解你的建議是好的。但是這是一個非常簡單的測試,它有一個連接到本地數據庫和一個表中的簡單SELECT。我非常驚訝Java的速度比使用OCCI的C++(C++的Oracle解決方案)快3倍。對我來說這是一個驚人的結果。 – filosofisto

+0

我懷疑Oracle的解決方案(OCCI)是否是一個好的解決方案。 – filosofisto

+0

您好馬丁,實際上當我平均抓取大小,差異是近似的,但JDBC仍然優於OCCI。 OCCI = 19s和JDBC = 12s。 – filosofisto