在我的情况下,SQL执行速度很慢


SQL execution being so slow on my case

我有一个关于我的代码的问题,这是我的代码连接到数据库,选择一些唯一的数据和求和这些唯一的数据从另一个表,我的代码没有问题,这一切都好,但它需要很长时间的查询。

<?php
include "koneksi.php";
$no=1;
$arqury=odbc_exec($koneksi, "SELECT DISTINCT NIP_AR,NAMA_AR FROM USRBPS.MASTERFILE");
while($ar=odbc_fetch_array($arqury)){
    $total=0;
    $ambilqury=odbc_exec($koneksi, "SELECT NPWP FROM USRBPS.MASTERFILE WHERE NIP_AR='$ar[NIP_AR]'");
    while($ambil=odbc_fetch_array($ambilqury)){
        $testqury=mysql_query("SELECT SUM(jumlah_bayar) as PENERIMAAN FROM mpnruteng WHERE npwp='$ambil[NPWP]'");
        $test=mysql_fetch_array($testqury);
        $total += $test[PENERIMAAN];
    }
    if($ar[NIP_AR]==""){
        echo "<tr><td>$no</td><td colspan=2>UNASSIGN</td><td>$total</td>";
    }
    else{
        echo "<tr><td>$no</td><td>$ar[NAMA_AR]</td><td>$ar[NIP_AR]</td><td>$total</td></tr>";
    }
    $no++;
}
?>

on就是这样,

|Name   |num_se
---------------
|andre  |1111
|john   |2222
|simon  |3333
|andre  |4444
|andre  |5555
|simon  |6666
|john   |7777

|num_se |Total
---------------
|1111   |12
|2222   |15
|3333   |10
|4444   |8
|5555   |20
|6666   |18
|7777   |22

所以,我需要的是得到'Total'的总和,从每个'Name'。我想获得的是名称"unique"的列表(在本例中是Andre, John和Simon),以及从num_se获得的每个"Total"的总和。

对不起,我的英语不好,但我希望你能理解。

解释一下您是在预先处理两个独立的数据源。

它很慢,因为你试图在PHP中循环你的结果集,调用单个查询从另一个表返回单行,这是非常低效的。

让数据库通过使用JOIN来处理两个相关表之间的关系,然后让它处理您的总总数,而不仅仅是单个总数。

下面的查询将获得nip_ar和nama_ar的每一对不同的总和:

SELECT 
  t1.NIP_AR,
  t1.NAMA_AR,
  SUM(t2.jumlah_bayar) as PENERIMAAN
FROM 
  USRBPS.MASTERFILE t1
  INNER JOIN mpnruteng t2
  ON t2.npwp = t1.npwp
GROUP BY
  1, 2

但是无论如何,你要把它卷成一个大的$total,所以这将为你得到它:

SELECT 
  SUM(PENERIMAAN) as PENERIMAAN
FROM 
  (
     SELECT 
       t1.NIP_AR,
       t1.NAMA_AR,
       SUM(t2.jumlah_bayar) as PENERIMAAN
     FROM 
       USRBPS.MASTERFILE t1
       INNER JOIN mpnruteng t2
       ON t2.npwp = t1.npwp
     GROUP BY
       1, 2
  )

你可以配置一个从oracle服务器到mySql服务器的链接。参考使用异构服务代理-第4章。设置对非oracle系统的访问。我的理解是你不能从mySql链接到Oracle。

这将允许您在您的Oracle实例上运行上述查询。尽管您需要更新表名以使其完全符合数据源名称

如果我理解正确,这个查询可能有帮助

SELECT t1.Name, sum(t2.Total) 
FROM (table1 t1 LEFT JOIN table2 t2 ON t1.num_se = t2.num_se)
GROUP BY t1.Name

根据大小写修改表名和列名。

我不知道你为什么使用两个分开的数据源。但是,我认为这种方法可以提高代码的效率。

首先,通过以下查询获得属于每个name的所有num_se的列表:

"SELECT Name, GROUP_CONCAT(num_se) as nums FROM table1 GROUP BY Name"

现在你的结果数组('$ar')将有一个元素"1111,2222",键为nums

其次,使用此查询获取每个name

的总和
"SELECT SUM(Total) as total FROM Table2 WHERE num_se IN (" . $ar['nums'] . ")"

您将获得每个nametotal,而不需要第二个循环。

请记住使用转义技术来确保您的查询是安全的

如果你在Windows上,我注意到使用localhost而不是127.0.0.1会减慢到数据库的连接。

在给出任何解决方案之前,我想分享一下您的查询太慢的原因。如果您仔细查看您的代码,您正在打开数据库连接,以便在第一个查询结果中达到记录。主要的开销是针对数据库打开和运行查询。所以想象一下,如果你在第一个结果中有1000条记录,你将打开数据库连接1000次,这将使它非常非常慢。使用Trung规定的内连接或子查询。如果不可能的话,使用存储过程并将逻辑放在SP中也可以帮助您获得性能。创建一个存储过程,并将输入参数作为从另一个数据库获得的以逗号分隔的id传递,在SP中使用逗号分隔的id来循环和执行选择语句。您可以使用临时表来实现这一点。这样做的好处是您只需要打开数据库连接一次。