重用数据库查询结果(Perl)

时间:2012-10-15 21:09:26

标签: perl cgi dbi

我正在使用Perl来填充两个html表(每个表都是在自己的Perl CGI脚本中生成的)。我有一个运行SQL查询的'helper'脚本。这是一个例子(让我们称这个脚本为run_sql_query.pl):

my $sql_query = "SELECT ID from TABLE where ID > 3";
our $sth = $dbh->prepare($sql_query);
$sth->execute;

然后,在我的两个Perl CGI脚本中,我做了:

require 'run_sql_query.pl';

our $sth;
while (my ($table_id) = $sth->fetchrow_array) {
...
}

但是,看起来run_sql_query.pl正在运行两次(每个Perl CGI脚本中运行一次)。我怎样才能这样run_sql_query.pl只执行一次,然后在两个Perl CGI脚本中使用相同的$sth内容?

3 个答案:

答案 0 :(得分:7)

如果我理解正确,您希望保存查询结果,以便其他进程可以再次使用它。这有几种方法,都涉及设置某种缓存。

CGI进程具有单独的内存,因此您不能直接执行您的要求。更糟糕的是,它们为每个请求启动和停止,浪费了大量的时间进行编译。但是,有很多方法可以解决这个问题。

如果您的SQL查询很昂贵,并且数据不经常更改,您可以让数据库缓存结果。例如,这是MySQL cache。这样做的好处是,使用数据库的所有内容都将使用它。缺点是您的程序仍然需要获取和处理所有数据。使用这个是你的查询很昂贵,但提取和处理它不是,而且你的数据不会经常改变。

另一种选择是设置外部缓存,例如memcached,以存储结果。 Memcached基本上是您机器上存储大量数据的服务器。或者您甚至可以使用数据库本身来缓存已处理的HTML表。每个进程都可以在自己计算之前检查他们想要的数据是否在缓存中。您可以使用CHI之类的东西与其进行交互。优点是你可以将任何你想要的东西放入缓存中。缺点是您必须自己管理缓存(即,当数据没有数据时删除数据),这是管理的另一件事,缓存可能随时消失。

最后,您可以更改流程的运行方式。一个基本的效率增益是从普通的CGI改变,它为每个请求启动,编译,运行和完成你的程序,到FastCGI之类的东西,它在你自己的小服务器上运行你的程序。可以把它想象成在整个程序中放置一个while循环。现在,由于您的程序没有在每个请求之间关闭,因此您可以将数据存储在全局变量中。然后,这是一个简单的事情来做@foampile建议的,将你的表存储在our @Table_Cache之类。这将为该进程缓存 ,但不会为其他人缓存。每个不同的程序都是自己的过程。因此foo.cgi不会与bar.cgi分享。优点是它很容易,FastCGI是你应该切换到的东西,你的网络服务器可能已经支持它。缺点是您需要管理缓存(即删除过期的条目),并且它不会跨进程共享。

我从FastCGI开始,看看是否能解决您的性能问题。这意味着每个服务器重启时,您只会两次运行每个查询,而不是每次请求。

答案 1 :(得分:1)

第一次遍历记录集时,您应该将查询结果提供给哈希或数据结构的哈希值,然后随后的时间只需要遍历或引用哈希/结构:

my $dataStruct;

while (my ($table_id) = $sth->fetchrow_array) { 
     my $colVal = $sth->data[...];
     $dataStruct->{$table_id}->{'col'} = $colVal;
} 

然后你迭代$ dataStruct。如果你需要指导如何做,请告诉我。

答案 2 :(得分:-1)

无法在进程(甚至线程)之间真正共享Perl变量。

但即使你可以,整个概念毫无意义。数据库无法知道它与两个客户交谈,因此一个客户端最终会得到一些记录,而另一个客户端会结束我们的其他一些记录。

您必须两次获取数据。您可以将数据存储在某个中间位置,并让两个客户端从那里获取数据,但您没有表明需要它。