2014-12-22 1 views
0

У меня есть этот скрипт perl, который берет данные из базы данных sqlplus ... эта база данных добавляет новую запись каждый раз, когда происходит изменение значения состояния для определенного последовательного номер. Теперь нам нужно выбрать записи при каждом изменении состояния и подготовить файл csv со старым состоянием состояния, нового состояния и другими. образец таблицы db.Как повысить эффективность скрипта perl, который использует sqlplus

SERIALNUMBER   STATE    AT      OPERATORID SUBSCRIBERID TRANSACTIONID 
51223344558899  Available   20081008T10:15:47   vsuser 
51223344558857  Available   20081008T10:15:49   vsowner 
51223344558899  Used     20081008T10:20:25   vsuser 
51223344558860  Stolen    20081008T10:15:49   vsanyone 
51223344558857  Damaged    20081008T10:50:49   vsowner 
51223344558899  Damaged    20081008T10:50:25   vsuser 
51343253335355  Available   20081008T11:15:47   vsindian 

мой сценарий:

#! /usr/bin/perl 

#use warnings; 
use strict; 


#my $circle = 
#my $schema = 
my $basePath = "/scripts/Voucher-State-Change"; 

#my ($sec, $min, $hr, $day, $month, $years) = localtime(time); 
#$years_+=1900;$mont_+=1; 
#my $timestamp=sprintf("%d%02d%02d",$years,$mont,$moday); 


sub getDate { 
    my $daysago=shift; 
    $daysago=0 unless ($daysago); 
    #my @months=qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec); 
    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time-(86400*$daysago)); 
    # YYYYMMDD, e.g. 20060126 
    return sprintf("%d%02d%02d",$year+1900,$mon+1,$mday); 
    } 

my $filedate=getDate(1); 
#my $startdate="${filedate}T__:__:__"; 
my $startdate="20081008T__:__:__"; 
print "$startdate\n"; 


##### Generating output file--- 
my $outputFile = "${basePath}/VoucherStateChangeReport.$filedate.csv"; 
open (WFH, ">", "$outputFile") or die "Can't open output file $outputFile for writing: $!\n"; 
print WFH "VoucherSerialNumber,Date,Time,OldState,NewState,UserId\n"; 



##### Generating log file--- 
my $logfile = "${basePath}/VoucherStateChange.$filedate.log"; 
open (STDOUT, ">>", "$logfile") or die "Can't open logfile $logfile for writing: $!\n"; 
open (STDERR, ">>", "$logfile") or die "Can't open logfile $logfile for writing: $!\n"; 
print "$logfile\n"; 

##### Now login to sqlplus----- 
my $SQLPLUS='/opt/oracle/product/11g/db_1/bin/sqlplus -S system/[email protected]'; 
`$SQLPLUS \@${basePath}/VoucherQuery1.sql $startdate> ${basePath}/QueryResult1.txt`; 


open (FH1, "${basePath}/QueryResult1.txt"); 

while (my $serial = <FH1>) { 
    chomp ($serial); 
    my $count = `$SQLPLUS \@${basePath}/VoucherQuery2.sql $serial $startdate`; 
    chomp ($count); 
    $count =~ s/\s+//g; 
    #print "$count\n"; 
    next if $count == 1; 

    `$SQLPLUS \@${basePath}/VoucherQuery3.sql $serial $startdate> ${basePath}/QueryResult3.txt`; 

# print "select * from sample where SERIALNUMBER = $serial----\n"; 
    open (FH3, "${basePath}/QueryResult3.txt"); 


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


      $count1++; 
      if ($count1 == 1) { 
       $old_state = $data[1]; 
       next; 
       } 

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

      print WFH "$serial_number,$date,$time,$old_state,$state,$operator_id\n"; 
      $old_state = $data[1]; 
      } 
     } 
close(WFH); 

запрос в VoucherQuery1.sql:

select distinct SERIALNUMBER from sample where AT like '&1'; 

запрос в VoucherQuery2.sql:

select count(*) from sample where SERIALNUMBER = '&1' and AT like '&2'; 

запрос в VoucherQuery2.sql:

select * from sample where SERIALNUMBER = '&1' and AT like '&2'; 

и мой пример вывода:

VoucherSerialNumber,Date,Time,OldState,NewState,UserId 
51223344558857,2008-10-08,10:50:49,Available,Damaged,vsowner 
51223344558899,2008-10-08,10:20:25,Available,Used,vsuser 
51223344558899,2008-10-08,10:50:25,Used,Damaged,vsuser 

Скрипт работает довольно хорошо. Но проблема в том, что фактическая таблица db имеет миллионы записей за определенный день ... и поэтому она поднимает проблемы с производительностью ... Не могли бы вы посоветовать, как мы можем повысить эффективность этого скрипта с точки зрения времени &. Единственное ограничение заключается в том, что я не могу использовать модуль DBI для этого ... Также в случае каких-либо ошибок в sql-запросах в файлы QueryResult ?.txt поступает сообщение об ошибке. Я хочу обрабатывать и получать эти ошибки в моем файле журнала. как это можно сделать? спасибо

+2

Кажется наиболее эффективным сделать обработку и построение результата внутри базы данных и заставить его автоматически выгружать результат в файл, минуя обработку результатов на Perl. Используйте хранимую процедуру. – reinierpost

+0

спасибо за ответ .. но я любопытный новичок в хранимых процедурах. Между тем я заменил первые два запроса на «выберите отличный SERIALNUMBER из (выберите d. *, Count (*) over (partition by SERIALNUMBER) cnt из образца d) где cnt> 1; " и он показывает улучшение ... – user2611539

ответ

0

Думаю, вам нужно настроить свой запрос. Хорошей отправной точкой является использование EXPLAIN PLAN, если это база данных Oracle.