以下是我的脚本的主要部分,它通过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';
但是数据库表包含数百万条记录,即使是简单的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问题,我不能将DBI
与DBD::Oracle
模块一起使用。我想自己解决这个问题,但需要你对这些性能问题的建议,因为我不能在它们上使用命中和遗漏方法。
答案 0 :(得分: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')
请注意,它不会产生与您自己的查询完全相同的结果,因为它将包含与给定serialnumber
相关的所有记录,只要这些记录中至少有一个与at
匹配的&1
列。