如何提高 sql 查询的性能?

How to enhance performance of sql query?

下面是我的脚本的主要部分,它通过 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})/-$month{}-/; 
               $date =~ s/(.*)(\d{2})(\d{2})//; 


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

但是数据库 table 包含数百万条记录,即使是简单的 select count(*) 查询也无法生成输出。现在的问题是创建数据库时没有定义约束。

我有编写脚本的经验,但就性能而言,我在 SQL 查询方面还是个新手。

我想问

这是table描述

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 模块一起使用。我想自己解决这个问题,但需要你对这些性能问题的建议,因为我不能对它们使用命中和未命中的方法。

我在 Oracle 方面的经验远不如其他数据库,所以这很可能不正确。但是,如果它有效,它肯定应该比现有的 SQL 更快,因为它在添加 previous 列之前限制了它正在处理的数据 first

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 相关的所有记录,只要 至少一个 的这些记录中有一个 at 列匹配 &1.