PHPBB Forum langsam

Hilfe bei technischen Problemen mit unserer Seite.
Antworten
Benutzeravatar
Captain
Major General
Major General
Beiträge: 18373
Registriert: So 02 Jan, 2005 19:50
Wohnort: Stuttgart

PHPBB Forum langsam

Beitrag von Captain »

Guten Morgen zusammen,

nachdem GRDB als solches eigentlich recht schnell läuft, ist es vor allem unser PHPBB Forum, welches mitunter recht langsam läuft. Das liegt natürlich an der deutlich gestiegenen Anzahl an Usern und auch an den immer mehr werdenden Posts. Ich werde daher in diesem Thread beschreiben, welche Codeoptimierungen ich in den einzelnen Skripten anwende, vielleicht hilft das dem einen oder anderen großen Forenbetreiber auch weiter. Ich würde mich freuen, wenn sich hierzu eine fundierte Diskussion ergibt. Mich würde interessieren, was andere Forenbetreiber in dieser Angelegenheit so alles unternehmen....

SEARCH.PHP

Die Suchfunktion schluckt nicht nur in der DB am meisten Ressorucen sondern auch bei ihrer Anwendung im Forum. Um das etwas zu verschlanken habe ich folgende Tune-Ups:

Code: Alles auswählen

						$sql = "SELECT topic_id
							FROM " . POSTS_TABLE . "
							WHERE post_id IN (" . implode(", ", $search_id_chunks[$i]) . ")
							$where_sql";
							GROUP BY topic_id";
Das GROUP BY-Statement kommt 2 mal vor. Bei größeren Boards ist es ratsam, dies zu entfernen und testweise auszukommentieren.

Code: Alles auswählen

						$sql = "SELECT topic_id
							FROM " . POSTS_TABLE . "
							WHERE post_id IN (" . implode(", ", $search_id_chunks[$i]) . ")
							$where_sql";
							//GROUP BY topic_id";
Benutzeravatar
Captain
Major General
Major General
Beiträge: 18373
Registriert: So 02 Jan, 2005 19:50
Wohnort: Stuttgart

Beitrag von Captain »

SEARCH.PHP

Der folgende Code

Code: Alles auswählen

//
// Look up data
//
      if ( $show_results == 'posts' )
      {
         $sql = "SELECT p.post_id
            FROM " . FORUMS_TABLE . " f, " . TOPICS_TABLE . " t, " . USERS_TABLE . " u, " . POSTS_TABLE . " p WHERE p.post_id IN ($search_results)
               AND f.forum_id = p.forum_id
               AND p.topic_id = t.topic_id
               AND p.poster_id = u.user_id";
      }
      else
      {
         $sql = "SELECT t.topic_id
            FROM " . TOPICS_TABLE . " t, " . FORUMS_TABLE . " f, " . USERS_TABLE . " u, " . POSTS_TABLE . " p, " . POSTS_TABLE . " p2, " . USERS_TABLE . " u2
            WHERE t.topic_id IN ($search_results)
               AND t.topic_poster = u.user_id
               AND f.forum_id = t.forum_id
               AND p.post_id = t.topic_first_post_id
               AND p2.post_id = t.topic_last_post_id
               AND u2.user_id = p2.poster_id";
      } 
wird bedeutend schneller in dieser Form ausgeführt:

Code: Alles auswählen

      switch ( $sort_by )
      {
         case 1:
         case 2:
                if ( $show_results == 'posts' )
                {
                    $sql = "SELECT p.post_id FROM " . TOPICS_TABLE . " t, " . POSTS_TABLE . " p WHERE p.post_id IN ($search_results) AND p.topic_id = t.topic_id ";
                }
                else
                {
                    $sql = "SELECT t.topic_id FROM " . TOPICS_TABLE . " t WHERE t.topic_id IN ($search_results) ";
                }
                $sql .= " ORDER BY ";
            $sql .= 't.topic_title';
            break;
         case 3:
                if ( $show_results == 'posts' )
                {
                    $sql = "SELECT p.post_id FROM " . USERS_TABLE . " u, " . POSTS_TABLE . " p WHERE p.post_id IN ($search_results) AND p.poster_id = u.user_id";
                }
                else
                {
                    $sql = "SELECT t.topic_id FROM " . TOPICS_TABLE . " t, " . USERS_TABLE . " u WHERE t.topic_id IN ($search_results) AND t.topic_poster = u.user_id ";
                }
                $sql .= " ORDER BY ";
            $sql .= 'u.username';
            break;
         case 4:
                if ( $show_results == 'posts' )
                {
                    $sql = "SELECT p.post_id FROM " . POSTS_TABLE . " p WHERE p.post_id IN ($search_results) ORDER BY p.forum_id ";
                }
                else
                {
                    $sql = "SELECT t.topic_id FROM " . TOPICS_TABLE . " t WHERE t.topic_id IN ($search_results)  ORDER BY t.forum_id ";
                }
            break;
         default:
                if ( $show_results == 'posts' )
                {
                    $sql = "SELECT post_id FROM " . POSTS_TABLE . " WHERE post_id IN ($search_results) ORDER BY post_id ";
                }
                else
                {
                    $sql = "SELECT topic_id FROM " . TOPICS_TABLE . " WHERE topic_id IN ($search_results) ORDER BY topic_last_post_id ";
                }
            break;
      } 
Benutzeravatar
Captain
Major General
Major General
Beiträge: 18373
Registriert: So 02 Jan, 2005 19:50
Wohnort: Stuttgart

Beitrag von Captain »

VIEWTOPIC.PHP

Bei JEDEM Zugriff auf ein Topic findet auch das Update der Views statt. Das kann bei großen Boards ein echtes Problem werden, zumal wenn wir ehrlich sind die Views eines Topics keiner sooooo genau nimmt. Ein Quick&Dirty Hack wäre folgendes:

Ersetze:

Code: Alles auswählen

        $sql = "UPDATE " . TOPICS_TABLE . " SET topic_views = topic_views + 1 WHERE topic_id = $topic_id";
        if ( !$db->sql_query($sql) )
        {
            message_die(GENERAL_ERROR, "Could not update topic views.", '', __LINE__, __FILE__, $sql);
        } 
durch

Code: Alles auswählen

    if (mt_rand(1,3) == 1) {
        $sql = "UPDATE " . TOPICS_TABLE . " SET topic_views = topic_views + 3 WHERE topic_id = $topic_id";
        if ( !$db->sql_query($sql) )
        {
            message_die(GENERAL_ERROR, "Could not update topic views.", '', __LINE__, __FILE__, $sql);
        }
    }
Is klar ne? Statt jeden Zugriff zu protokollieren wird statistisch gesehen jeder dritte Zugriff verdreifacht. Damit ist man zumindest statistisch wieder da wo man ohnehin gelandet wäre, aber mit einer Reduktion der Update-Routinen um 66%. Genau ist diese Lösung natürlich nicht, aber im Mittel stimmt der Wert.
Benutzeravatar
Captain
Major General
Major General
Beiträge: 18373
Registriert: So 02 Jan, 2005 19:50
Wohnort: Stuttgart

Beitrag von Captain »

INDEX.PHP

Auch an der Startseite kann man einiges drehen. Zum Beispiel dies:

Code: Alles auswählen

if ( $userdata['session_logged_in'] )
{
$sql = "SELECT t.forum_id, t.topic_id, p.post_time
FROM " . TOPICS_TABLE . " t, " . POSTS_TABLE . " p
WHERE p.post_id = t.topic_last_post_id
AND p.post_time > " . $userdata['user_lastvisit'] . "
AND t.topic_moved_id = 0";
if ( !($result = $db->sql_query($sql)) )
{
message_die(GENERAL_ERROR, 'Could not query new topic information', '', __LINE__, __FILE__, $sql);
}

$new_topic_data = array();
while( $topic_data = $db->sql_fetchrow($result) )
{
$new_topic_data[$topic_data['forum_id']][$topic_data['topic_id']] = $topic_data['post_time'];
}
}
Normalerweise startet die Index damit alle Foren zu durchsuchen, inwieweit neue Antworten seit dem letzten Besuch hinzugekommen sind. Schön und gut, kann aber bei großen Foren Probleme machen. Hier ein kleiner Hack:

Code: Alles auswählen

sql = "SELECT f.*, p.post_time, p.post_username, u.username, u.user_id
FROM (( " . FORUMS_TABLE . " f
LEFT JOIN " . POSTS_TABLE . " p ON p.post_id = f.forum_last_post_id )
LEFT JOIN " . USERS_TABLE . " u ON u.user_id = p.poster_id )
ORDER BY f.cat_id, f.forum_order";

if ( !($result = $db->sql_query($sql)) )
{
message_die(GENERAL_ERROR, 'Could not query forums information', '', __LINE__, __FILE__, $sql);
}

$forum_data = array();
while( $row = $db->sql_fetchrow($result) )
{
$forum_data[] = $row;
if ($row['post_time'] > $userdata['user_lastvisit']) $new_topic_data[$row['forum_id']][$row['topic_id']] = $row['post_time'];
}
Antworten