2014-02-05 164 views
0

我通過記錄每分鐘在線的用戶來監視服務器上的玩家活動。玩家列表作爲一個逗號分隔的字符串存儲在varchar字段中。如何提高從MySql數據庫處理數據的速度

我讓玩家選擇一個日期來顯示在該日期和月份中誰在線。

該腳本運行良好,並做它應該做的,除了它需要很長時間來處理數據的方式,我正在做它。目前大約需要10秒才能加載頁面。

我的問題是:是否有一種更高效,更快速的獲取和顯示數據的方式?

This is the webpage顯示玩家活動。

if(isset($_POST['submit'])){ 

    $chosenDay =$_POST['day']; 
    $chosenMonth =$_POST['month']; 
    $chosenYear =$_POST['year']; 
    ?> 
<article id="intro"> 
    <div id="motd"> 
    <h2>Player Activity Graph</h2> 
    <form class="form" action="activity.php" method="POST"> 
    <select name="year" class="date-select"> 
    <?php 
     echo '<option value="'.$chosenYear.'" selected>'.$chosenYear.'</option>'; 
     for($i = 2013; $i<$currentYear; $i++){ 
      echo '<option value="'.$i.'">'.$i.'</option>'; 
     } 
    ?> 

    </select> 
    <select name="month" class="date-select"> 
    <?php 
     echo '<option value="'.$chosenMonth.'" selected>'.$chosenMonth.'</option>'; 
     for($i = 1; $i<12; $i++){ 
      echo '<option value="'.$i.'">'.$i.'</option>'; 
     } 
    ?> 
    </select> 
    <select name="day" class="date-select"> 
    <?php 
     echo '<option value="'.$chosenDay.'" selected>'.$chosenDay.'</option>'; 
     for($i = 1; $i<=$days_in_month; $i++){ 
      echo '<option value="'.$i.'">'.$i.'</option>'; 
     } 
    ?> 
    </select> 
    <input type="submit" name="submit" id="activitysubmit" value="submit" /> 
    </form> 
    </div> 

    <p>Please select a date and press submit. You will be presented with a<br /> graph of player activity. Hover over a bar to view the players online at<br /> that time.</p><br /><br /> 


    <?php 
    $chosenDate =$chosenYear.'-'.$chosenMonth.'-'.$chosenDay; 

    $get = $dbh->prepare("SELECT * FROM dcpmc_players_online WHERE date=?"); 
    $get->bindParam(1, $chosenDate, PDO::PARAM_STR); 
    $get->execute(); 
    $result = $get->fetchAll(); 
    if(count($result) > 0){ 


     $left = 0; 
     echo '<div class="chartWrapper">'; 
     echo '<p>Players online today</p>'; 
     echo '<div class="sidelegend"><p>Player count</p></div>'; 
     echo '<div class="bottomlegend"> 
     <div class="time"><p>0</p></div>  
     <div class="time"><p>1</p></div>  
     <div class="time"><p>2</p></div>  
     <div class="time"><p>3</p></div>  
     <div class="time"><p>4</p></div>  
     <div class="time"><p>5</p></div>  
     <div class="time"><p>6</p></div>  
     <div class="time"><p>7</p></div>  
     <div class="time"><p>8</p></div>  
     <div class="time"><p>9</p></div>  
     <div class="time"><p>10</p></div> 
     <div class="time"><p>11</p></div> 
     <div class="time"><p>12</p></div> 
     <div class="time"><p>13</p></div> 
     <div class="time"><p>14</p></div> 
     <div class="time"><p>15</p></div> 
     <div class="time"><p>16</p></div> 
     <div class="time"><p>17</p></div> 
     <div class="time"><p>18</p></div> 
     <div class="time"><p>19</p></div> 
     <div class="time"><p>20</p></div> 
     <div class="time"><p>21</p></div> 
     <div class="time"><p>22</p></div> 
     <div class="time"><p>23</p></div> 
     <div class="time"><p>24</p></div> 
     </div>'; 
     echo '<div class="bottomlegend2"><p>Time in GMT</p></div>'; 
     // loop through every hour of today 
     for($h = 0; $h<=$hours; $h++){ 

      // add a zero in front of the first 9 hours 
      if($h < 10){$h='0'.$h;} 

      // loop through every minute of this hour 
      for($m = 0; $m<=$minutes; $m++){ 

       // add a zero in front of the first 9 minutes 
       if($m == 0){$m = '0'.$m;} 

       if($m == 00 || $m == 15 || $m == 30 || $m == 45){ 
        // build current time to check for players 
        $thisTime = $h.':'.$m.':00'; 

        // get players online at this time in this hour of chosen date 
        $get = $dbh->prepare("SELECT * FROM dcpmc_players_online WHERE time=? AND date=?"); 
        $get->bindParam(1, $thisTime, PDO::PARAM_STR); 
        $get->bindParam(2, $chosenDate, PDO::PARAM_STR); 
        $get->execute(); 
        $now = $get->fetchAll(); 
         if(count($now) > 0){ 
          foreach($now AS $index){ 
          $hoverDate = $index['time']; 
          $playerExplode = explode(",", $index['players']); 
          if(count($playerExplode == 1)){ 
           foreach($playerExplode AS $index){ 
            if($index == 'none'){ 
             $playerCount = 0; 
            }else{ 
             $playerCount = count($playerExplode); 
            } 
           } 
          } 

          $left = $left+5; 
          $barHeight = $playerCount * 8; // 200px high container/50 players = 8px per 1 player 
          echo '<div class="barContainer"><div class="bar1" style="height:'.$barHeight.'px;left:'.$left.'px;"></div>'; 

          echo '<div class="hoverInfo"><p>'.$hoverDate.'</p><br />'; 
          if($playerCount > 0){ 
           echo '<p>'.$playerCount.' players online</p><br />'; 
           foreach($playerExplode AS $index){ 
            echo '<p>'.$index.' </p>'; 
           } 
          }else{ 
           echo '<p>No players online.</p>'; 
          } 


          echo '</div>'; 
          echo '</div>'; 
          } 

         } 

正如你可以看到我使用for遍歷每個小時的每一分鐘,我是這樣假設是導致長時間的延遲進行迭代。

數據庫表的結構是這樣的:

enter image description here

+0

您是否在日期字段中設置了索引? – jeff

+0

不,我已經設置主鍵爲用戶ID – crm

+2

您正在運行此查詢60次或更多,看起來:'SELECT * FROM dcpmc_players_online WHERE time =? AND date =?'。您可以在兩個時間範圍內抓取所有行(在一個查詢中),然後循環接收的數據。 – degenerate

回答

2

有一些事情可以做,即更換*在你選擇具有隻顯示與觀衆的字段。

您還可以建立數據庫條目,以在玩家登錄時寫入「條目記錄」,並在退出時寫入「退出記錄」。這樣,你只能在每個會話中抓取兩個記錄,而不是每個在線玩家每分鐘1個。然後,您可以調整您的SELECT來計算該人是否有當天的入場記錄,並返回「是」值。同樣,您可以讓PHP找到會話入口和出口記錄,並顯示該會話的各種信息。

如果您想確定它們已經打開並且沒有斷開連接,那麼您也可以像現在一樣每分鐘進行一次檢查,如果它們不在服務器上,但最後一項是登錄,手動輸入註銷記錄,因爲它們可能已斷開連接並且記錄未創建。

我還建議添加分配給每個入口和出口的會話ID以使所有計算更容易。

相關問題