PHP / MySQL 很慢,不知道为啥?

Posted

技术标签:

【中文标题】PHP / MySQL 很慢,不知道为啥?【英文标题】:PHP / MySQL is slow, can't figure out why?PHP / MySQL 很慢,不知道为什么? 【发布时间】:2016-03-08 09:21:08 【问题描述】:

第一个函数recentlyModified() 准确地在 1 秒内运行,即使它正在轮询两个节目。我承认,它可以使用的参数要少得多,但这在每场演出大约 0.5 秒的情况下非常快。

第二个函数myList() 然而,4 个标题大约需要 16 秒,2 个标题需要 11 秒,一个标题需要 6 秒。这当然是平均水平。

<?php

include_once './php/loadanime.php';

function crunchyrollNews() 
    echo('<iframe class="rss fullwidth fullheight" src="http://feeds.feedburner.com/crunchyroll/animenews?format=xml"></iframe>');


function recentlyModified($count) 
    $mtime = microtime();
   $mtime = explode(" ",$mtime);
   $mtime = $mtime[1] + $mtime[0];
   $starttime = $mtime;

    $animedb = new mysqli("localhost", "animedeck", "W8a7fs5gu");

    $query = $animedb->query("SELECT id, img, name, description  FROM animedeck.animelist ORDER BY modified DESC LIMIT " . $count . "");    

    if($query) 
        $result = $query->fetch_all();

        echo '<div class="recentanimemodule">';

        echo '<h1 class="h1 borderb">AnimeDeck Recent</h1>';

            foreach($result as $id) 
                echo '<div class="recentanimepiece">';
                echo '<img class="recentanimeposter" src="';
                echo $id[1];
                echo '" />';    
                echo '<a class="recentanimeurl" href="'; //a href start
                echo './viewanime.php?id=' . $id[0]; 
                echo '">';
                echo '<div class="recentanimename">';
                echo $id[2];
                echo '</div>';
                echo '</a>'; //a href end
                echo '<div class="recentanimedes">';
                echo $id[3];
                echo '</div>';  
                echo '</div>';
            

        echo '</div>';
     else 
        echo "Failed to retrieve entries.";
    

       $mtime = microtime();
   $mtime = explode(" ",$mtime);
   $mtime = $mtime[1] + $mtime[0];
   $endtime = $mtime;
   $totaltime = ($endtime - $starttime);
   echo "This module was created in ".$totaltime." seconds"; 


function myList($status, $sort, $startindex, $count) 

    $mtime = microtime();
   $mtime = explode(" ",$mtime);
   $mtime = $mtime[1] + $mtime[0];
   $starttime = $mtime;

    $animedb = new mysqli("localhost", "animedeck", "W8a7fs5gu");
    $orderby;
    $title = "Recent";
    $rstatus = ", status='" . $status . "'";

    if($status == "all") 
        $rstatus = null;
    

    if($startindex == null) 
        $startindex = 0;    
    

    switch ($sort) 
    case "recent":
        $sort = "DESC";
        $orderby="modified";
        $title = "Recent";
        break;
    case "oldest":
        $sort = "ASC";
        $orderby="modified";
        $title = "Oldest";
        break;
    case "az":
        $sort = "ASC";
        $orderby="animename";
        $title = "A to Z";
        break;
    case "za":
        $sort = "DESC";
        $orderby="animename";
        $title = "Z to A";
        break;
    

    $query = $animedb->query("SELECT animeid FROM animedeck.mylist WHERE userid='" . $_SESSION['userid'] . "' " . $rstatus . " ORDER BY " . $orderby . " " . $sort . " LIMIT " . $startindex . ", " . $count . ""); 

    if($query) 
        $result = $query->fetch_all();


        echo '<div class="myanimemodule">';

        echo '<h1 class="h1 borderb">MyList ' . $title . '</h1>';

            foreach($result as $id) 
                $info = loadSemiAnime($id[0]);

                echo '<div class="animeid">' . $id[0] . '</div>';
                echo '<div class="myanimepiece">';
                echo '<img class="myanimeposter" src="';
                echo $info['img'];
                echo '" />';    
                echo '<a class="myanimeurl" href="'; //a href start
                echo './viewanime.php?id=' . $id[0]; 
                echo '">';
                echo '<div class="myanimename">';
                echo $info['name'];
                echo '</div>';
                echo '</a>'; //a href end
                echo '<div class="myanimedes">';
                echo $info['description'];
                echo '</div>';  
                echo '</div>';
                echo '<div class="animelistoptions">';
                echo '<span onClick="setStatus(' . $id[0] . ', \'';
                echo loadAnime($id[0], "name") . "'";
                echo ', 0)" id="stowatch' . $id[0] . '" class="bluebutton">To Watch</span>';
                echo '<span onClick="setStatus(' . $id[0] . ', \'';
                echo loadAnime($id[0], "name") . "'";
                echo ', 1)" id="swatching' . $id[0] . '" class="bluebutton">Watching</span>';
                echo '<span onClick="setStatus(' . $id[0] . ', \'';
                echo loadAnime($id[0], "name") . "'";
                echo ', 2)" id="swatched' . $id[0] . '" class="bluebutton">Seen</span>';
                echo '<span onClick="setStatus(' . $id[0] . ', \'';
                echo loadAnime($id[0], "name") . "'";
                echo ', 3)" id="srewatching' . $id[0] . '" class="bluebutton">Re-Watching <i class="fa fa-heart"></i></span>';
                echo '</div>';

                echo '<script>getStatus(' . $id[0] . ');</script>';
            

        echo '</div>';
     else 
        echo "Failed to retrieve entries. Error: " . $animedb->errno . " --- " . $animedb->error;
    


       $mtime = microtime();
   $mtime = explode(" ",$mtime);
   $mtime = $mtime[1] + $mtime[0];
   $endtime = $mtime;
   $totaltime = ($endtime - $starttime);
   echo "This module was created in ".$totaltime." seconds"; 



?>

所以我的问题是我不确定我的代码中的什么导致它需要这么长时间?一次迭代需要 6 秒?是PHP吗?我认为 MySQL 执行得很快,所以我认为它是 PHP。但是哪一部分呢?

我不熟悉 PHP 的好坏习惯,所以我不知道是什么真正减慢了我的功能。

这是我的 loadAnime() 和 loadSemiAnime() 函数:

<?php 

function loadAnime($id, $toload) 

    $animedb = new mysqli("localhost", "animedeck", "W8a7fs5gu");
    $load = $animedb->query("SELECT " . $toload . " FROM animedeck.animelist WHERE id=" . $id . "");

    if($load) 
        $result = $load->fetch_assoc();

        echo $result[$toload];
       


function loadSemiAnime($id) 
    $animedb = new mysqli("localhost", "animedeck", "W8a7fs5gu");
    $load = $animedb->query("SELECT img, name, description FROM animedeck.animelist WHERE id=" . $id . "");

    if($load) 
        $result = $load->fetch_assoc();
        return $result;
           


?>

【问题讨论】:

尝试“EXPLAIN SELECT Animeid FROM Animedeck.mylist WHERE userid=...”并发布结果 loadAnime() 和 loadSemiAnime() 函数有什么作用。 天啊...非常感谢 Kickstart。我知道每次需要一个变量时运行整个查询是不好的,所以我创建了 loadSemiAnime 类来加载我需要的三个变量,然后重用这些变量。但是我忘了把那些在那里。我现在正式降到 4 秒,即每场 1 秒。这很棒。但现在我认为我可以在总体表现上做得更好。目前我的数据库运行良好,所以我想真正的下一步是尝试优化代码然后优化数据库? 为我的加载功能添加到了hastebin中。 那些函数(不确定你是否还在使用它们)每次执行时都会连接到数据库。这是另一个开销以及每次执行查询时都会执行查询。 【参考方案1】:

您的查询是动态构建的,因此很难在那里看到任何内容,但构建它看起来很简单,所以我怀疑查询非常简单。

但是,您拥有连接到数据库并对主查询返回的每条记录进行查询的函数。这些似乎没有必要,因为看起来您可以通过 JOIN 来获取主查询中的字段:-

SELECT a.animeid, b.img, b.name, b.description
FROM animedeck.mylist a
LEFT OUTER JOIN animedeck.animelist b
ON a.animeid = b.id
WHERE a.userid='" . $_SESSION['userid'] . "' " . $rstatus . " ORDER BY " . $orderby . " " . $sort . " LIMIT " . $startindex . ", " . $count . "

【讨论】:

所以如果我实现它,它应该或多或少的工作? LEFT OUTER JOIN 总结起来有什么作用? LEFT OUTER JOIN 是将两个表连接在一起,但右边的表不需要有匹配的行(在这种情况下,该表中的列将具有 NULL 值) . 非常感谢。这使我的执行时间减少到 1 秒,即使我要获得 4 个标题。从现在开始我将不得不使用这个加入的东西!太奇妙了!谢谢你。 :)【参考方案2】:

这也是问题所在。

$query = $animedb->query("SELECT animeid FROM animedeck.mylist WHERE userid='" . $_SESSION['userid'] . "' " . $rstatus . " ORDER BY " . $orderby . " " . $sort . " LIMIT " . $startindex . ", " . $count . ""); 

您的“用户 ID”在您的 where 子句中,如果该字段不是索引,那么在大表上这将非常慢。进入您的 MySQL 表并为该列添加索引,例如。

ALTER TABLE `animedeck` ADD INDEX `userid` (`userid`)

这应该会大大加快速度。

一般经验法则,where 子句中的任何字段都需要索引。 MySql 默认会索引主键。因此您无需手动索引主键(即 ID 字段)。

【讨论】:

【参考方案3】:

好吧,我最终按照此处的建议实施了对数据库设置的所有更改:https://www.percona.com/blog/2006/09/29/what-to-tune-in-mysql-server-after-installation/

【讨论】:

我的数据库是与 Plesk 一起安装的,所以我不知道是否已经对其进行了优化。我正在运行 Windows Server 2012。

以上是关于PHP / MySQL 很慢,不知道为啥?的主要内容,如果未能解决你的问题,请参考以下文章

查询在 mysql 工作台中有效,但在 php 中无效,不知道为啥

为啥每次启动电脑都会很慢

php在连接mysql时为啥会包这样的错误?

php通过公网ip链接mysql,速度很慢,如何解决?

Linux下mysql读写速度为啥很慢

我centOS上的MySQL速度很慢