2015-04-05 92 views
-1

下面是我的腳本的主要部分,它通過SQL * Plus與Oracle數據庫進行交互。如何提高sql查詢的性能?

#--------------- Now connecting to sqlplus 

     `$SQLPLUS \@${basePath}/VoucherQuery.sql $startdate> ${basePath}/logs/QueryResult.$currentDate.log`; 
     if ($? == 0) { 
      logger("Processing with the sqlplus is completed. For more details check ${basePath}/logs/QueryResult.$currentDate.log ", 0); } 
     else { 
      logger("Not able to fetch data from sqlplus. Please check", 1); exit;} 



     #print "select * from sample where SERIALNUMBER = $serial\n"; 

     open (FH, "${basePath}/logs/QueryResult.$currentDate.log") or die "Can't open query ${basePath}/logs/QueryResult.$currentDate.log file: $!\n"; 

     my ($serial_number, $state, $at, $operator_id, $old_state); 
     while (my $data = <FH>) { 
       chomp ($data); 
       #print $data."\n";   
       my @data = split (/\s+/, $data); 
       my ($serial_number, $state, $at, $operator_id, $old_state) = @data[0..4]; 


       my ($date, $time) = split (/T/, $at); 
       $date =~ s/(\d{4})(\d{2})(\d{2})/$3-$month{$2}-$1/; 
       $date =~ s/(.*)(\d{2})(\d{2})/$1$3/; 


       print WFH "$circle,$date,$time,$operator_id,$serial_number,$old_state,$state\n"; 
       } 
      close(FH); 
    close(WFH); 

------------------------------------------------------------- 
>cat VoucherQuery.sql 
SELECT * FROM (SELECT serialnumber, state, at, operatorid, lag(state) OVER (PARTITION BY serialnumber ORDER BY at) AS previous FROM VOUCHER) WHERE at LIKE '&1'; 

但數據庫表中包含數百萬條記錄,甚至一個簡單的select count(*)查詢是不是能夠產生輸出。現在問題是在創建數據庫時沒有定義約束。

我有腳本編程的經驗,但就性能而言,我在SQL查詢方面相當不錯。

我想問

  • 多少區別它會使如果我定義表中的主鍵約束? (這是一個第三方服務器,所以在做任何修改之前我必須確定。)

  • 索引是否會提高性能?他們怎麼能幫助這個具體的查詢?

  • 我應該將此查詢分解爲更多,更簡單的查詢嗎?

下面是表描述

SQL> DESC VOUCHER; 
Name      Null?     Type 
-------------------------- -------- ------------------------------- 
SERIALNUMBER       VARCHAR2(20) 
STATE         VARCHAR2(4000) 
AT         VARCHAR2(4000) 
OPERATORID       VARCHAR2(4000) 
SUBSCRIBERID       VARCHAR2(20) 
TRANSACTIONID       VARCHAR2(20) 

一兩件事。我必須處理SQL * Plus,但由於Solaris問題,我無法使用DBIDBD::Oracle模塊。我想自己解決這個問題,但需要你就這些性能問題提出建議,因爲我不能在它們上使用命中和錯過方法。

+0

您的'cat'輸出看起來像是'VoucherQuery.sql'的內容而不是'QueryResult。$ currentDate.log'的內容?在你的查詢中,它看起來像'serialnumber'不是唯一的,所以除非Oracle允許非唯一主鍵,否則如果你聲明'serialnumber'是主鍵,它會中斷 – Borodin 2015-04-05 06:57:21

+0

什麼是*「Solaris問題」*阻止您使用DBI?有了數百萬條記錄,我認爲你永遠不會使用該SQL進行合理的反應時間,因爲它始於以每個序列號的狀態列的前一個值提取整個數據庫。一旦它完成了,它會通過'at'來過濾結果,並且可能會拋棄剛剛完成的大部分工作。我會先從'SELECT DISTINCT serialnumber FROM voucher WHERE'LIKE'&1''開始,然後*然後*將每條記錄與之前的狀態關聯起來。 'serialnumber'上的一個*索引*(不是PK)會很好。 – Borodin 2015-04-05 07:10:31

+0

@Borodin謝謝你的迴應..你是對的..我糾正了我的錯誤..但是主要不是非唯一的價值......在這裏主鍵和國家的組合可能是PK ..它會產生什麼影響? 這裏是對DBI的解釋「http://www.perlmonks.org/?node=Not+able+to+install+DBD%3A%3AOracle+on+sun+solaris。「我不會介意是否需要太多時間才能執行......但問題是......它只是等待並且即使在一小時內也沒有響應......我會嘗試」DISTINCT「選項並讓你知道...... – Ankur 2015-04-05 07:34:32

回答

0

我在Oracle方面的經驗比其他數據庫少得多,所以這可能不是正確的。但是如果它起作用,肯定會比現有的SQL更快,因爲它在添加previous列之前限制了它在第一個上工作的數據。

SELECT 
    serialnumber, 
    state, 
    at, 
    operatorid, 
    LAG(state) OVER (PARTITION BY serialnumber ORDER BY at) AS previous 
FROM 
    voucher 
WHERE 
    serialnumber in (SELECT DISTINCT serialnumber FROM voucher WHERE at LIKE '&1') 

注意,也不會產生相同的結果作爲自己的查詢,因爲這將包括只要至少一個這些記錄有匹配的at柱與給定serialnumber所有記錄&1

+0

謝謝..我會嘗試這個&會回覆你... – Ankur 2015-04-05 07:36:26