简体   繁体   English

低效的MySQL数据库/语句降低了PHP / JS系统的运行速度

[英]Inefficient MySQL database/statements slowing PHP/JS system down

I have developed a fairly ramshackle PHP/JavaScript Reward system for my school's VLE. 我为学校的VLE开发了一个相当麻烦的PHP / JavaScript奖励系统。

The main bulk of the work is done on a transactions table which has the following fields: 大部分工作是在具有以下字段的transactions表上完成的:

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

The idea is that if I, as a member of staff, give a student some Reward Points, an entry such as this is inserted into the database: 这个想法是,如果我作为教职员工给学生一些奖励积分,则将这样的条目插入数据库:

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.');

This worked fine - but I didn't really consider just how much the system would be used. 这很好用-但我并没有真正考虑过要使用多少系统。 I now have over 72,000 transactions in this table. 现在,此表中有超过72,000个事务

As such, a few of my pages are starting to slow down. 因此,我的一些页面开始变慢。 For instance, when staff try to allocate points, my system runs a command to get the member of staff's total point allocation and other snippets of information. 例如,当员工尝试分配积分时,我的系统运行命令以获取员工的总积分分配和其他信息片段。 This appears to be displaying rather slowly, and looking at the MySQL statement/accompanying PHP code, I think this could be much more efficient. 这似乎显示得相当慢,并且查看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;
}

As such, my question is twofold. 因此,我的问题是双重的。

  1. Can this specific code be optimised? 可以优化此特定代码吗?
  2. Can I employ any database techniques - full text indexing or the like - to further optimise my system? 我可以采用任何数据库技术-全文索引之类-来进一步优化我的系统吗?

EDIT : RE Indexing 编辑 :RE索引

I don't know anything about indexing, but it looks like my transactions table does actually have an index in place? 我对索引一无所知,但看起来我的transactions表确实有索引吗?

交易表索引

Is this the correct type of index? 这是正确的索引类型吗?

Here is the code for table-creation: 这是表创建的代码:

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 ;

Thanks in advance, 提前致谢,

Make sure Giver_ID is indexed . 确保Giver_ID编制索引 Try also running the strtotime outside of your while loop as I imagine its an expensive operation to be running 72,000 times. 还尝试在您的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"];
        }
    }
}

Also consider running UNIX_TIMESTAMP(Datetime) AS datetime_timestamp in your SQL instead of getting it out as a string and running another expensive strtotime operation. 还可以考虑在您的SQL中运行UNIX_TIMESTAMP(Datetime) AS datetime_timestamp ,而不是将其作为字符串获取并运行另一个昂贵的strtotime操作。 You can then simply run: 然后,您可以简单地运行:

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

(if your column is of type DATE, of course!) (当然,如果您的列是DATE类型的!)

72k is nothing... However there could be other things here that are causing slowdowns, like your mysql configuration (how much memory you allocated to the service), and a few others (do a search for optimizing mysql). 72k没什么...但是这里可能还有其他原因导致速度变慢,例如您的mysql配置(您为服务分配了多少内存)和其他一些内容(进行了搜索以优化mysql)。

Also look at how many INSERTS you have in a given page, that will typically slow down your page load, if you are doing an insert every action for a user, you are making a costly transaction. 还要查看给定页面中有多少INSERTS ,这通常会减慢页面加载速度,如果您要为用户执行插入操作,那么您的交易成本很高。

Typically a SELECT is much less expensive than an INSERT, etc; 通常,SELECT比INSERT等便宜得多。

From your SQL code I can also assume you didn't optimize your queries, something like: 从您的SQL代码中,我还可以假设您没有优化查询,例如:

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

Should be: 应该:

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

(not a big issue from your data, but it only requests WHAT YOU NEED, not everything which would require more memory while going through the iteration). (这不是您数据中的大问题,但它仅要求您需要什么,而不要求在迭代过程中需要更多内存的所有内容)。

Also not sure how your schema is designed, but are you using indexing on Transaction_ID ? 也不确定您的架构是如何设计的,但是您是否在Transaction_ID上使用索引?

Can this specific code be optimized? 可以优化此特定代码吗?

Yes. 是。
But definitively not by "looking at the code". 但绝对不是通过“查看代码”。

Can I employ any database techniques - full text indexing or the like - to further optimise my system? 我可以采用任何数据库技术-全文索引之类-来进一步优化我的系统吗?

Nope, you can't. 不,你不能。
Simply because you have no idea, what certainly is slow in your system. 仅仅是因为您不知道,所以系统中肯定存在缓慢。

This is merely a common sense, widely used in the real life by anyone, but for some reason it become completely forgotten when someone start to program a web-site. 这只是一个常识,在现实生活中被任何人广泛使用,但是由于某些原因,当有人开始对网站进行编程时,它就被完全忘记了。

Your question is like "my car is getting slow. How to speed it up?". 您的问题就像“我的车越来越慢。如何加快速度?”。 WHO ON THE EARTH CAN ANSWER IT, knowing no reason of the slowness? 世卫组织可以回答这个问题,不知道缓慢的原因吗? Is it tyres? 是轮胎吗? Or gasoline? 还是汽油? Or there is no road around but an open field? 还是只有一片空旷的土地,没有路可走? Or just someone forgot to release a hand brake? 还是只是有人忘记释放手刹?

You have to determine the slowness reason first. 您必须先确定运行缓慢的原因。

Before asking a question you have to measure your query runtime. 提出问题之前,您必须衡量您的查询运行时间。
And if it's still fast, you should not blame it for the slowness of your site. 而且,如果它仍然很快,则不应将其归因于网站的缓慢。
And start profiling it. 并开始进行分析

First of all you have to determine what part of the whole page makes it load slow. 首先,您必须确定整个页面的哪一部分使其加载缓慢。 It could be just some Javascript loading from the third-party server. 它可能只是从第三方服务器加载的一些Javascript。
So, start with "Net" tab in the Firebug and see the most slow part. 因此,从Firebug中的“ Net”选项卡开始,然后查看最慢的部分。

then proceed to it. 然后继续进行。
If it's your PHP code - use microtime(1); 如果是您的PHP代码-请使用microtime(1); to measure different parts to spot the problem one. 测量不同部分以发现问题之一。

Then come with the question. 然后提出问题。

However, if take your question not as a request for the speed optimization, but for the more sanity in SQL, there are some improvements that can be made. 但是,如果您的问题不是对速度优化的要求,而是对SQL的更多理智,则可以进行一些改进。

Both numbers can be retrieved as a single values. 这两个数字都可以作为单个值检索。

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

will give you tital points 会给你点滴
as well as 以及

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

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

will give you weekly points. 将为您提供每周积分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM