需要PHP / SQL(MySQL)函数优化帮助

时间:2010-08-12 18:32:57

标签: sql mysql optimization query-optimization

我目前正在尝试优化在应用程序中真正称为“瓶颈”的功能。

在相关应用程序中,可以选择选项。但是有些选择可能受到其他选择的限制。例如,选择选项“A”时,它会限制选项“B”的选择。

这些限制链接保存到具有以下结构的表中:

option_restrictions
    option_code_1    varchar(20)
    option_code_2    varchar(20)

另外一些选项是选项包。例如,选项“水果”包括选项“Apple”,“Orange”,“Kiwi”。

这些在表格中以这种方式定义:

option_packages
    option_code        varchar(20)
    option_included    varchar(20)

目前“瓶颈”功能可以做到这一点:

  1. 检查2个指定选项是否相互限制。
  2. 如果没有,则检查选项1是否为选项包,如果是,则检查所有选项并检查选项是否受限于选项2.
  3. 如果没有,它会检查选项2是否为选项包,如果是,则检查所有选项,并检查选项是否受限于选项1.
  4. 如果不是,则返回false(无限制)。
  5. 以下是我正在尝试优化的实际代码:

    //Returns true if options restricts each other, false otherwise
    function restriction($option_1, $option_2) {
        global $conn;
    
        //Pass 1 check is each option restrict themselves
        $sql_restriction = "select * from option_restrictions where (option_code_1 = '".$option_1."' or option_code_1 = '".$option_2."') and (option_code_2 = '".$option_1."' or option_code_2 = '".$option_2."')";
        $res_restriction = mysql_query($sql_restriction, $conn);
        if (mysql_num_rows($res_restriction)>0) {
            log_action('End restriction(' . $option_1 . ', ' . $option_2 . ')');
            return true;
        } else {
            //Pass 2 check if option 1 is a package and if so test it's options against option 2
            $sql_option_1_composante = "select * from option_packages where option_code = '".$option_1."'";
            $res_option_1_composante = mysql_query($sql_option_1_composante, $conn);
            if (mysql_num_rows($res_option_1_composante)>0) {
                while ($option_1_composante = mysql_fetch_array($res_option_1_composante)) {
                    if (restriction($option_1_composante["option_included"], $option_2)) {
                        return true;
                    }
                }
            }
            //Pass 3 check if option 2 is a package and if so test it's options against option 1
            $sql_option_2_composante = "select * from option_packages where option_code = '".$option_2."'";
            $res_option_2_composante = mysql_query($sql_option_2_composante, $conn);
            if (mysql_num_rows($res_option_2_composante)>0) {
                while ($option_2_composante = mysql_fetch_array($res_option_2_composante)) {
                    if (restriction($option_2_composante["option_included"], $option_1)) {
                        return true;
                    }
                }
            }
        }
    
        return false;
    }
    

    递归调用/循环正在杀死系统ATM ...对于单页加载,此函数可以被调用超过15,000次,这导致页面加载30秒/ 4分钟!

    我正尽力优化。我已经尝试将第2和第3传递合并并删除递归调用...欢迎任何想法!

    仅供参考,我知道这可能不是最好的设计,但这个功能是我无法控制的利维坦系统的一部分,也不是改变自动柜员机的资源/时间。

1 个答案:

答案 0 :(得分:1)

如果没有更多详细信息,我无法确定,但对我而言,这听起来像是数据库设计问题。

如果确实是数据库设计问题,

  • 你可能不会变得非常 远远优化应用程序代码
  • 但改变结构可能会大大减少加载时间,甚至可能会降低几个数量级

这是我通过概念验证测试成功攻击的那种问题(遗留系统,不允许更改它)。我在自己的计算机上安装了一台服务器。 (Oracle XE,SQL Server Express和PostgreSQL现在都是免费的。)然后我会构建表格和视图来完成所有繁重的工作。

在您的情况下,如果您不是数据库设计师,请找一个愿意参与臭鼬工作项目的人。

祝你好运。我的意思是。