2015-04-05 90 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