Oracle 如何提高sql查询的性能?

Oracle 如何提高sql查询的性能?,oracle,performance,perl,shell,sqlplus,Oracle,Performance,Perl,Shell,Sqlplus,下面是我的脚本的主要部分,它通过SQL*Plus与Oracle数据库交互 #--------------- Now connecting to sqlplus `$SQLPLUS \@${basePath}/VoucherQuery.sql $startdate> ${basePath}/logs/QueryResult.$currentDate.log`; if ( $? == 0) { logger("Processi

下面是我的脚本的主要部分,它通过SQL*Plus与Oracle数据库交互

  #--------------- 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';

还有一件事。我必须处理SQL*Plus,但由于Solaris问题,我不能将
DBI
DBD::Oracle
模块一起使用。我想自己解决这个问题,但需要您对这些性能问题的建议,因为我不能对它们使用命中和未命中的方法。

与其他数据库相比,我在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')

请注意,它不会产生与您自己的查询完全相同的结果,因为它将包括与给定的
serialnumber
相关的所有记录,只要这些记录中至少有一条在
处有一列与
&1
匹配的

您的
cat
输出看起来像是
VoucherQuery.sql
而不是
QueryResult.$currentDate.log
?从您的查询来看,
serialnumber
似乎不是唯一的,因此,除非Oracle允许非唯一主键,否则我认为如果您将
serialnumber
声明为主键,它将崩溃。阻止您使用DBI的“Solaris问题”是什么?对于数以百万计的记录,我认为使用该SQL永远不会有合理的反应时间,因为它首先使用每个序列号的state列的前一个值获取整个数据库。一旦这样做了,它就会通过
at
过滤结果,并可能会丢弃它刚刚完成的大部分工作。首先,我将执行
从凭证中选择不同的序列号,其中类似于“&1”
,然后将每条记录与其以前的状态关联起来。
serialnumber
上的索引(不是PK)会很好。@Borodin感谢您的回复。。你是对的。。我已经改正了我的错误。。但主值不能是非唯一值。。。这里主键和状态的组合可以是PK。。这会有什么影响吗?这是关于DBI的解释。“我不介意执行的时间太长。”。。但问题是。。它只是一直在等待,甚至在一个小时内都没有响应。我会尝试“独特”选项并让你知道。。。
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')