2012-01-10 71 views
1

我在下面的場景中運行,這讓我頗爲頭疼,因爲我無法找到我所看到的行爲的確切解釋。我有以下聲明:Pro * C性能差異

struct test_struct 
{ 
    long testv1; 
    char testv2[51]; 
    long testv3; 
}; 

,並在Oracle 10g中相應的表:

CREATE TABLE test_table 
(
    testv1 NUMBER(10, 0), 
    testv2 VARCHAR(50), 
    testv3 NUMBER(4, 0) 
); 

要在此表中訪問數據我有一個函數:

bool getTestData(long test_var1, struct test_struct *outStruct) 

,在這裏我看到我需要解釋但不能的差異。如果函數體看起來是這樣的:

EXEC SQL BEGIN DECLARE SECTION; 
    long testvar1_param = test_var1; 
    struct test_struct *resStruct = outStruct; 
EXEC SQL END DECLARE SECTION; 

EXEC SQL SELECT testv1, testv2, testv3 
    INTO :resStruct 
    FROM test_table 
    WHERE testv1 = :testvar1_param; 

我得到性能更慢那麼如果函數體中的樣子:

EXEC SQL BEGIN DECLARE SECTION; 
    long testvar1_param = test_var1; 
    long *testv1_res = &(outStruct->testv1); 
    char *testv2_res = outStruct->testv2; 
    long *testv3_res = &(outStruct->testv3); 
EXEC SQL END DECLARE SECTION; 

EXEC SQL SELECT testv1, testv2, testv3 
    INTO :testv1_res, :testv2_res, :testv3_res 
    FROM test_table 
    WHERE testv1 = :testvar1_param; 

在第二個表現是由顯著邊緣不同。

有誰知道什麼可以解釋這種行爲?

回答

1

對於第一眼看不到的性能問題:打開包括等待的SQL跟蹤。

ALTER SESSION SET TRACEFILE_IDENTIFIER = "some_unique_identifier"; 
dbms_support.start_trace (binds=>true,waits=>true); 

運行您的代碼,使其提交併正常斷開連接。不要使用dbms_support.stop_trace,因爲它可能會妨礙對源行操作的後臺處理。 在生成的跟蹤文件中,您可以在分析時找到確切的sql文本,等待影響sql和rowsource操作的事件。行源操作顯示sql計劃在運行sql時的樣子。

  • 檢查解析的數量
  • 檢查綁定變量被使用或沒有。
  • 檢查預期計劃的行源操作。

您的問題 - 有一個隨機的方式來獲取大量的行之一 - 我希望找到

  • 1遊標聲明
  • 1解析
  • 打開一個循環/獲取/關閉光標

這些場景對於不分析每個選擇非常重要。解析可能需要比執行更多的時間。

剩下的一個問題是:爲什麼要逐一獲取所有行?這是某種數據複製操作嗎?

+0

由於這是由其他人構建的,並試圖重新構建此解決方案將花費大量時間,這不是數據複製操作。不幸的是,這更多地用於IPC。不要拍攝信使我沒有拿出這個... – Karlson 2012-01-11 15:01:26

+0

嘗試使描述的痕跡和檢查結果。沒有拍攝從我身邊,我來平安;-) – 2012-01-11 15:21:17

+0

@卡爾森你發現了什麼? – 2012-01-13 06:29:09

1

你是否考慮了緩存的影響?我不假設。

如果您運行第一個查詢timed,然後運行第二個查詢timed,其中testvar1_param值相同,第二個查詢完成時間明顯不同。首先運行哪個查詢並不重要,第二個版本會更好。

這是因爲where謂詞在兩個查詢中都是相同的,並且結果集中的數據在兩個查詢中都是相同的。通常,隨後的查詢相同的查詢在針對索引查詢時運行速度會快得多,因爲您從不去獲取結果集,而是從SGA緩存它。

嘗試對testvar1_param使用不同的值,並使用完全不同的parm值運行10個查詢。他們將會非常接近時間。

您正在使用tkprof嗎?

+0

我正在考慮緩存的影響。在執行前後使用gettimeofday()完成的時間。查詢是在多天內對相同的一組數據運行的,其間數據庫重新啓動。而testvar1_param是隨機的。 – Karlson 2012-01-10 17:55:49

+0

必須有其他的事情發生 - 我不會在9i和11g的桌面上運行你的代碼,這些代碼有2200萬行和隨機參數。 PS:總是打開sqltrace(和計時),然後通過tkprof運行.trc文件。長城時間在欺騙。你的讀取時間不同?什麼oracle版本? – 2012-01-10 18:43:38

+0

我個人提取時間取決於個人提取5至100毫秒。第二個在4ms左右相當一致。 Oracle版本是10.2.0.4 – Karlson 2012-01-10 19:46:20

0

通過時間我的意思(因爲它是發展的,對不對?)

ALTER SYSTEM SET TIMED_STATISTICS = TRUE; 

這提高了Oracle爲您提供了跟蹤性能。

+0

您可能想要合併這兩個答案。 – Karlson 2012-01-11 15:36:02