花费很长时间执行复杂的 mySql 查询

Posted

技术标签:

【中文标题】花费很长时间执行复杂的 mySql 查询【英文标题】:Taking long time executing complex mySql query 【发布时间】:2015-03-05 08:25:38 【问题描述】:

我的查询如下所示:

$result_portlist=mysql_query("
    SELECT 
        portfolio AS the_port,
        SUM(balance * course) AS the_balance,
        SUM(insurance * course) AS the_insurance
        FROM banks_all 
    WHERE CONCAT(balance, insurance)!='0'
    GROUP BY portfolio
    ",$db);

$myrow_portlist=mysql_fetch_array($result_portlist); 
if(mysql_num_rows($result_portlist)>0)  
    do  
        echo '<span> value1, vaule2, value3...</span>';

        $result_portlist1=mysql_query("
            SELECT 
                department AS the_department,
                SUM(balance * course) AS the_balance,
                SUM(insurance * course) AS the_insurance
            FROM banks_all 
            WHERE CONCAT(balance, insurance)!='0'
                AND portfolio='$myrow_portlist[the_port]' 
            GROUP BY department
        ",$db);

        $myrow_portlist1=mysql_fetch_array($result_portlist1); 
        if (mysql_num_rows($result_portlist1)>0)  
            do  
                echo '<span> value1, vaule2, value3...</span>'

                $result_portlist2=mysql_query("
                    SELECT 
                        manager_name AS the_manager,
                        SUM(balance * course) AS the_balance,
                        SUM(insurance * course) AS the_insurance
                    FROM banks_all
                    WHERE CONCAT(balance, insurance)!='0'
                        AND portfolio='$myrow_portlist[the_port]' 
                        AND department='$myrow_portlist1[the_department]'
                    GROUP BY manager_name
                ",$db);

                 
                    do 
                        echo '<span> value1, vaule2, value3...</span>';
                     while ($myrow_portlist2=mysql_fetch_array($result_portlist2));
                 
             while ($myrow_portlist1=mysql_fetch_array($result_portlist1)); 
         
     while ($myrow_portlist1=mysql_fetch_array($result_portlist1)); 
 

因此,对于具有 40,000 多行和数百种 portfolio+department+manager_name 组合的表,此查询需要数小时才能执行。我的想法是在开始时进行一个查询,将值按manager_name 分组,然后让php 分组portfoliodepartment。创建此查询后,我的大脑刚刚炸毁,没有可用的内存来思考:)

请告诉我如何重新排列此查询或如何简化它以减少执行时间。

提前致谢。

编辑:这是图片,我的表(带有嵌套表)的样子:

IMAGE

【问题讨论】:

尽可能合并查询 乍一看,您似乎可以使用一个查询(使用连接)来收集所有数据。所有 3 个表似乎只由 2 个字段连接,所以应该没有那么困难。 感谢您的回答。但不是&lt;span&gt;,我得到了一个复杂的表,它将显示portfolio 的总值,然后当我单击特定的portfolio 时,它将打开按department 分组的嵌套表,当我单击特定的department 时,它将打开按manager_name 分组的嵌套表。在这种情况下 JOIN 会有所帮助吗? 所以对查询做一个解释,看看 MySQL 是如何实际执行它的,并向我们展示表结构以及这些表上任何索引的详细信息 @user3137740 所以你想一开始就加载嵌套表的数据?我会把这些嵌套的东西放在一个单独的 AJAX 请求中,然后按需加载。这将大大减少要传输的数据量。 【参考方案1】:

花费大量时间的原因是您正在执行大量查询...假设您有 10 个投资组合,在 10 个部门中,您将进行 100 个查询。这个数量太疯狂了,在您的情况下减少查询数量非常简单。

我会简单地在一个查询中获取所有数据,并使用一个 3 级 group by 和一个汇总:

$result=mysql_query("
    SELECT 
        portfolio AS the_port,
        department AS the_department,
        manager_name AS the_manager,
        SUM(balance * course) AS the_balance,
        SUM(insurance * course) AS the_insurance
    FROM banks_all 
    WHERE 
        CONCAT(balance, insurance)!='0'
    GROUP BY 
        portfolio,
        department,
        manager_name 
    with ROLLUP
    ORDER BY the_port,the_department,the_manager;
",$db);
echo '<table>';
while($row = mysql_fetch_assoc($result))
    if($row['the_port'] === null)
        //This is the big total row... Let's skip it for now shall we?
        continue;
    
    echo '<tr>';
    if($row['the_department'] === null)
        echo '<td>Portfolio: '.$row['the_port'].'</td>';
    else
        if($row['the_manager'] === null)
            echo '<td>Department: '.$row['the_port'].'</td>';
        else
            echo '<td>Manager: '.$row['the_port'].'</td>';
        
    
    echo '<td>'.$row['the_balance'].'</td>';
    echo '<td>'.$row['the_insurance'].'</td>';
    echo '</tr>';

echo '</table>';

此查询将返回按投资组合分组、然后按部门分组、然后按经理分组的所有行。这将从最好的点(您的第三个时间)返回所有行,但使用ROLLUP,您还将按级别为其他组获得一行。这与您在同一个查询中完成 GROUP BY portfolio,departmentGROUP BY portfolio 完全相同。

在汇总的行中,从 group by 中省略的键的值将为 NULL。所以你可以很容易地查看the_manager,当它为空时,意味着你拥有完整的部门,当the_department为空时,你拥有完整的投资组合。

【讨论】:

哇!它看起来正是我需要的。我现在就试试这个。当我测试它时会报告。 好吧,我测试了它,但我无法为我拥有的表分隔行(见图)。 在汇总的行中,从 group by 中省略的键的值将为 NULL。所以你可以很容易地检查 the_manager,当它为空时意味着你拥有完整的部门,当 the_department 为空时你拥有完整的投资组合。 - 我忘了尝试这部分...... 我已经编辑了我的答案,添加了一个 order by statement 和一些 php 代码以显示类似于您想要的内容。

以上是关于花费很长时间执行复杂的 mySql 查询的主要内容,如果未能解决你的问题,请参考以下文章

我想减少 MYSQL 查询执行时间。我的查询需要很长时间?

如果使用 ORDER BY String Column,MySQL 查询需要很长时间才能执行

MySQL 查询:长时间处于“init”状态

ORDER BY RAND()函数在mysql中执行需要很长时间[重复]

Mysql Join Query需要很长时间才能执行

MySql 查询需要很长时间 PHP