效率低下的MySQL数据库/语句会降低PHP / JS系统的速度

时间:2012-04-25 12:45:16

标签: php mysql optimization

我为学校的VLE开发了一个相当摇摇欲坠的PHP / JavaScript奖励系统。

工作的主要部分是在transactions表上完成的,该表包含以下字段:

Transaction_IDDatetimeGiver_IDRecipient_IDPointsCategory_IDReason

我的想法是,如果我作为工作人员向学生提供一些奖励积分,则会在数据库中插入此条目:

INSERT INTO `transactions` (`Transaction_ID`, `Datetime`, `Giver_ID`, `Recipient_ID`, `Points`, `Category_ID`, `Reason`) VALUES
(60332, '2012-02-22', 34985, 137426, 5, 5, 'Excellent volcano homework.');

这很好用 - 但我并没有真正考虑系统的使用量。我现在在此表中已超过 72,000笔交易

因此,我的一些页面开始变慢。例如,当员工尝试分配积分时,我的系统会运行一个命令来获取员工的总点数分配和其他信息片段。这似乎显示得相当慢,并且查看MySQL语句/随附的PHP代码,我认为这可能会更有效。

function getLimitsAndTotals($User_ID) {

    $return["SpentTotal"] = 0;
    $return["SpentWeekly"] = 0;

    $sql = "SELECT * 
        FROM `transactions` 
        WHERE `Giver_ID` =$User_ID";
    $res = mysql_query($sql);

    if (mysql_num_rows($res) > 0) {
        while ($row = mysql_fetch_assoc($res)) {
            $return["SpentTotal"] += $row["Points"];

            $transaction_date = strtotime ($row["Datetime"]);

            if ($transaction_date > strtotime( "last sunday" )) {
                $return["SpentWeekly"] += $row["Points"];
            }
        }
    }

    return $return;
}

因此,我的问题是双重的。

  1. 可以优化此特定代码吗?
  2. 我可以使用任何数据库技术 - 全文索引等 - 来进一步优化我的系统吗?

  3. 编辑:RE索引

    我对索引没有任何了解,但看起来我的transactions表确实有一个索引吗?

    Transaction table index

    这是正确的索引类型吗?

    以下是表创建的代码:

    CREATE TABLE IF NOT EXISTS `transactions` (
      `Transaction_ID` int(9) NOT NULL auto_increment,
      `Datetime` date NOT NULL,
      `Giver_ID` int(9) NOT NULL,
      `Recipient_ID` int(9) NOT NULL,
      `Points` int(4) NOT NULL,
      `Category_ID` int(3) NOT NULL,
      `Reason` text NOT NULL,
      PRIMARY KEY  (`Transaction_ID`)
    ) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=74927 ;
    

    提前致谢,

3 个答案:

答案 0 :(得分:1)

确保Giver_ID 已编入索引。尝试在while循环之外运行strtotime,因为我认为它运行72,000次是一项昂贵的操作。

if (mysql_num_rows($res) > 0) {

    // assign the unix timestamp of last sunday here.
    $last_sunday = strtotime('last sunday');

    while ($row = mysql_fetch_assoc($res)) {
        $return["SpentTotal"] += $row["Points"];

        $transaction_date = strtotime ($row["Datetime"]);

        if ($transaction_date > $last_sunday) {
            $return["SpentWeekly"] += $row["Points"];
        }
    }
}

还要考虑在SQL中运行UNIX_TIMESTAMP(Datetime) AS datetime_timestamp,而不是将其作为字符串运行并运行另一个昂贵的strtotime操作。然后你可以简单地运行:

if (mysql_num_rows($res) > 0) {

    // assign the unix timestamp of last sunday here.
    $last_sunday = strtotime('last sunday');

    while ($row = mysql_fetch_assoc($res)) {
        $return["SpentTotal"] += $row["Points"];

        if ($row['datetime_timestamp'] > $last_sunday) {
            $return["SpentWeekly"] += $row["Points"];
        }
    }
}

(如果你的专栏是DATE类型的话,当然!)

答案 1 :(得分:0)

72k没什么......但是这里可能还有其他的东西导致速度减慢,比如你的mysql配置(你分配给服务的内存多少),以及其他一些(搜索优化mysql)。 / p>

另请查看给定页面中有多少INSERTS,这通常会减慢页面加载速度,如果您为用户执行每个操作的插入操作,那么您的交易成本很高。

通常,SELECT比INSERT等便宜得多;

从您的SQL代码中我还可以假设您没有优化查询,例如:

$sql = "SELECT * 
    FROM `transactions` 
    WHERE `Giver_ID` =$User_ID";

应该是:

$sql = "SELECT Points, DateTime FROM ..."

(不是你的数据中的一个大问题,但它只是请求你需要的东西,而不是在进行迭代时需要更多内存的所有内容)。

还不确定您的架构是如何设计的,但是您是否在Transaction_ID使用索引?

答案 2 :(得分:0)

  

可以优化此特定代码吗?

是。
但最终不是“看代码”。

  

我可以使用任何数据库技术 - 全文索引等 - 来进一步优化我的系统吗?

不,你不能。
只需因为你不知道,你的系统当然有什么缓慢。

这仅仅是一种常识,在现实生活中被任何人广泛使用,但由于某种原因,当有人开始编写网站时,它会完全被遗忘。

你的问题就像是“我的车变慢了。如何加快速度?”。地球上的谁可以回答它,知道没有缓慢的原因?它是轮胎吗?还是汽油?或者周围没有道路而是开阔的田野?或者只是有人忘记释放手刹?

您必须首先确定缓慢原因。

提出问题之前,您必须衡量查询运行时间 如果它仍然很快,你不应该因为网站的缓慢而责怪它 并开始分析

首先,您必须确定整个页面的哪个部分使其加载缓慢。它可能只是从第三方服务器加载的一些Javascript 因此,从Firebug中的“Net”选项卡开始,看看最慢的部分。

然后继续。
如果是您的PHP代码 - 使用microtime(1);来衡量不同的部分以发现问题。

然后提出问题。

但是,如果不是将您的问题作为速度优化的请求,而是为了在SQL中更加健全,那么可以进行一些改进。

这两个数字都可以作为单个值检索。

select sum(Points) as Total from FROM `transactions` WHERE Giver_ID=$User_ID

会给你点数 以及

$sunday = date("Y-m-d",strtotime('last sunday'));

select sum(Points) as Spent from FROM `transactions` 
WHERE Giver_ID=$User_ID AND Datetime > '$sunday'

会给你每周积分。