Bug tracker

This ticket has been moved to our new tracker. Open Ticket PHPBB3-7063 now.

Poor query format for display online list (fix completed in vcs)

In the functions.php page_header(); function, the display online list query can cause higher load than needed.
The SESSIONS_TABLE/USERS_TABLE joined query pulls all of the records in the SESSIONS table and then PHP runs through and filters them, but they could be filtered through SQL.
There is already a query to grab the guests browsing a specific forum or the entire board, but it is only used if $config['load_online_guests'] is set to true, yet the information retrieved is no different than the inner joined query.

I provided a patch below to (hopefully) illustrate my thoughts on this portion of code.
The difference should mean improved performance especially for large boards as it would pull significantly less rows on the joined query, yet returns the same data.

http://phpfi.com/300804
Code: Select all
Index: functions.php
===================================================================
--- functions.php   (revision 8423)
+++ functions.php   (working copy)
@@ -3152,78 +3152,61 @@
       }
 
       // Get number of online guests
-      if (!$config['load_online_guests'])
+      if ($db->sql_layer === 'sqlite')
       {
-         if ($db->sql_layer === 'sqlite')
-         {
-            $sql = 'SELECT COUNT(session_ip) as num_guests
-               FROM (
-                  SELECT DISTINCT s.session_ip
-                     FROM ' . SESSIONS_TABLE . ' s
-                     WHERE s.session_user_id = ' . ANONYMOUS . '
-                        AND s.session_time >= ' . (time() - ($config['load_online_time'] * 60)) .
-                        $reading_sql .
-               ')';
-         }
-         else
-         {
-            $sql = 'SELECT COUNT(DISTINCT s.session_ip) as num_guests
-               FROM ' . SESSIONS_TABLE . ' s
-               WHERE s.session_user_id = ' . ANONYMOUS . '
-                  AND s.session_time >= ' . (time() - ($config['load_online_time'] * 60)) .
-               $reading_sql;
-         }
-         $result = $db->sql_query($sql);
-         $guests_online = (int) $db->sql_fetchfield('num_guests');
-         $db->sql_freeresult($result);
+         $sql = 'SELECT COUNT(session_ip) as num_guests
+            FROM (
+               SELECT DISTINCT s.session_ip
+                  FROM ' . SESSIONS_TABLE . ' s
+                  WHERE s.session_user_id = ' . ANONYMOUS . '
+                     AND s.session_time >= ' . (time() - ($config['load_online_time'] * 60)) .
+                     $reading_sql .
+            ')';
       }
+      else
+      {
+         $sql = 'SELECT COUNT(DISTINCT s.session_ip) as num_guests
+            FROM ' . SESSIONS_TABLE . ' s
+            WHERE s.session_user_id = ' . ANONYMOUS . '
+               AND s.session_time >= ' . (time() - ($config['load_online_time'] * 60)) .
+            $reading_sql;
+      }
+      $result = $db->sql_query($sql);
+      $guests_online = (int) $db->sql_fetchfield('num_guests');
+      $db->sql_freeresult($result);
 
-      $sql = 'SELECT u.username, u.username_clean, u.user_id, u.user_type, u.user_allow_viewonline, u.user_colour, s.session_ip, s.session_viewonline
+      $sql = 'SELECT u.username, u.username_clean, u.user_id, u.user_type, u.user_allow_viewonline, u.user_colour, s.session_viewonline
          FROM ' . USERS_TABLE . ' u, ' . SESSIONS_TABLE . ' s
          WHERE s.session_time >= ' . (time() - (intval($config['load_online_time']) * 60)) .
             $reading_sql .
-            ((!$config['load_online_guests']) ? ' AND s.session_user_id <> ' . ANONYMOUS : '') . '
+            ' AND s.session_user_id <> ' . ANONYMOUS . '
             AND u.user_id = s.session_user_id
-         ORDER BY u.username_clean ASC, s.session_ip ASC';
+         ORDER BY u.username_clean ASC';
       $result = $db->sql_query($sql);
 
       while ($row = $db->sql_fetchrow($result))
       {
-         // User is logged in and therefore not a guest
-         if ($row['user_id'] != ANONYMOUS)
+         // Skip multiple sessions for one user
+         if ($row['user_id'] != $prev_user_id)
          {
-            // Skip multiple sessions for one user
-            if ($row['user_id'] != $prev_user_id)
+            if ($row['session_viewonline'])
             {
-               if ($row['session_viewonline'])
-               {
-                  $logged_visible_online++;
-               }
-               else
-               {
-                  $row['username'] = '<em>' . $row['username'] . '</em>';
-                  $logged_hidden_online++;
-               }
-
-               if (($row['session_viewonline']) || $auth->acl_get('u_viewonline'))
-               {
-                  $user_online_link = get_username_string(($row['user_type'] <> USER_IGNORE) ? 'full' : 'no_profile', $row['user_id'], $row['username'], $row['user_colour']);
-                  $online_userlist .= ($online_userlist != '') ? ', ' . $user_online_link : $user_online_link;
-               }
+               $logged_visible_online++;
             }
+            else
+            {
+               $row['username'] = '<em>' . $row['username'] . '</em>';
+               $logged_hidden_online++;
+            }
 
-            $prev_user_id = $row['user_id'];
-         }
-         else
-         {
-            // Skip multiple sessions for one user
-            if ($row['session_ip'] != $prev_session_ip)
+            if (($row['session_viewonline']) || $auth->acl_get('u_viewonline'))
             {
-               $guests_online++;
+               $user_online_link = get_username_string(($row['user_type'] <> USER_IGNORE) ? 'full' : 'no_profile', $row['user_id'], $row['username'], $row['user_colour']);
+               $online_userlist .= ($online_userlist != '') ? ', ' . $user_online_link : $user_online_link;
             }
          }
 
-         $prev_session_ip = $row['session_ip'];
+         $prev_user_id = $row['user_id'];
       }
       $db->sql_freeresult($result);
 

Comments / History

Posted by Kellanved (Former Team Member) on Mar 6th 2008, 10:54

Yes, we are aware of the issue.

Posted by rxu (Development Team Member) on Mar 9th 2008, 08:30

It would be nice also (for MOD authors at least, imho) if online list to be a separate function :)

Posted by Highway of Life (QA Team) on Mar 10th 2008, 18:28

Well you can disable it by setting the second argument in the page_header(); to false.

Posted by rxu (Development Team Member) on Mar 11th 2008, 14:38

Yes. I've meant a possibility for MOD authors to use online list apart of page_header function. Just a suggestion.

Assigned ticket to user "Kellanved"

Action performed by Acyd Burn (Server Manager) on Mar 13th 2008, 14:50

Linked ticket with changeset: r8436

Action performed by Kellanved (Former Team Member) on Mar 17th 2008, 16:25

Changed ticket status from "New" to "Fix completed in SVN"

Action performed by Kellanved (Former Team Member) on Mar 17th 2008, 16:51

Posted by rxu (Development Team Member) on Mar 17th 2008, 17:41

Kellanved
Thanks for making guests/users lists separate functions.

Ticket details

Related SVN changesets