1

我为我学校的 VLE 开发了一个相当不稳定的 PHP/JavaScript 奖励系统。

主要工作是在transactions具有以下字段的表上完成的:

Transaction_ID, Datetime, Giver_ID, Recipient_ID, Points, Category_ID,Reason

这个想法是,如果我作为一名教职员工,给学生一些奖励积分,则会将这样的条目插入到数据库中:

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. 我可以使用任何数据库技术(全文索引等)来进一步优化我的系统吗?

编辑:重新索引

我对索引一无所知,但看起来我的transactions表确实有一个索引?

事务表索引

这是正确的索引类型吗?

这是创建表的代码:

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 ;

提前致谢,

4

3 回答 3

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"];
        }
    }
}

还要考虑UNIX_TIMESTAMP(Datetime) AS datetime_timestamp在您的 SQL 中运行,而不是将其作为字符串取出并运行另一个昂贵的 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 类型!)

于 2012-04-25T12:50:49.093 回答
0

72k 什么都不是……但是这里可能还有其他导致速度变慢的事情,例如您的 mysql 配置(您为服务分配了多少内存),以及其他一些(搜索优化 mysql)。

还要查看INSERTS给定页面中有多少个,这通常会减慢页面加载速度,如果您为用户执行插入每个操作,那么您将进行昂贵的交易。

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

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

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

应该:

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

(从您的数据来看不是一个大问题,但它只要求您需要什么,而不是在迭代过程中需要更多内存的所有内容)。

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

于 2012-04-25T12:50:49.913 回答
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'

会给你每周积分。

于 2012-04-25T13:19:08.717 回答