3

我正在使用 Perl 填充两个 html 表(每个表都是在其自己的 Perl CGI 脚本中生成的)。我有一个运行 SQL 查询的“助手”脚本。这是一个例子(我们称之为脚本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只执行一次,然后$sth在两个 Perl CGI 脚本中使用相同的内容?

4

3 回答 3

7

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

CGI 进程有单独的内存,所以你不能直接做你问的事情。更糟糕的是,它们会为每个请求启动和停止,从而浪费大量时间进行编译。但是,有很多方法可以解决这个问题。

如果您的 SQL 查询开销很大,并且数据不经常更改,您可以让数据库缓存结果。例如,这里是MySQL 缓存。这样做的好处是所有使用数据库的东西都将使用它。缺点是您的程序仍然必须获取和处理所有数据。使用它是您的查询很昂贵,但获取和处理它不是,并且您的数据不会经常更改。

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

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

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

于 2012-10-15T21:44:38.927 回答
1

您应该在第一次遍历记录集时将查询结果提供给哈希哈希或数据结构,然后再通过或引用哈希/结构:

my $dataStruct;

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

然后稍后您遍历 $dataStruct。如果您需要指导如何做到这一点,请告诉我。

于 2012-10-15T21:14:54.097 回答
-1

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

但即使你可以,整个概念也毫无意义。数据库无法知道它正在与两个客户端对话,因此一个客户端会以某些记录结束,而另一个会以其他一些记录结束我们。

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

于 2012-10-15T21:46:29.493 回答