我为学校的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;
}
因此,我的问题是双重的。
编辑:RE索引
我对索引没有任何了解,但看起来我的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 ;
提前致谢,
答案 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'
会给你每周积分。