From a37254a976502a342a863ece8b285b96faff9494 Mon Sep 17 00:00:00 2001
From: mattab <matthieu.aubry@gmail.com>
Date: Sat, 6 Dec 2014 01:53:27 +1300
Subject: [PATCH] The ultimate prize and final step to close the issue: do not
 group by the whole set of matched rows, way too slow on huge datasets!

---
 core/DataAccess/LogQueryBuilder.php       | 10 +++++++---
 plugins/Live/tests/System/ModelTest.php   |  1 -
 tests/PHPUnit/Integration/SegmentTest.php |  3 +--
 3 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/core/DataAccess/LogQueryBuilder.php b/core/DataAccess/LogQueryBuilder.php
index ac55ccf454..a5b2fcf986 100644
--- a/core/DataAccess/LogQueryBuilder.php
+++ b/core/DataAccess/LogQueryBuilder.php
@@ -184,14 +184,18 @@ class LogQueryBuilder
         $innerSelect = implode(", \n", $neededFields);
         $innerFrom = $from;
         $innerWhere = $where;
-        $innerGroupBy = "log_visit.idvisit";
-        $innerLimit = $limit;
 
+        $innerLimit = $limit;
+        $innerGroupBy = "log_visit.idvisit";
         $innerOrderBy = "NULL";
-        // Only when there is a LIMIT then we can apply to the inner query the same ORDER BY as the parent query
         if($innerLimit && $orderBy) {
+            // only When LIMITing we can apply to the inner query the same ORDER BY as the parent query
             $innerOrderBy = $orderBy;
         }
+        if($innerLimit) {
+            // When LIMITing, no need to GROUP BY (GROUPing by is done before the LIMIT which is super slow when large amount of rows is matched)
+            $innerGroupBy = false;
+        }
 
         $innerQuery = $this->buildSelectQuery($innerSelect, $innerFrom, $innerWhere, $innerGroupBy, $innerOrderBy, $innerLimit);
 
diff --git a/plugins/Live/tests/System/ModelTest.php b/plugins/Live/tests/System/ModelTest.php
index 90196e7309..268a7861d4 100644
--- a/plugins/Live/tests/System/ModelTest.php
+++ b/plugins/Live/tests/System/ModelTest.php
@@ -91,7 +91,6 @@ class ModelTest extends SystemTestCase
                           AND log_visit.visit_last_action_time >= ?
                           AND log_visit.visit_last_action_time <= ? )
                           AND ( log_link_visit_action.custom_var_k1 = ? )
-                        GROUP BY log_visit.idvisit
                         ORDER BY idsite, visit_last_action_time DESC
                         LIMIT 100
                         ) AS log_inner
diff --git a/tests/PHPUnit/Integration/SegmentTest.php b/tests/PHPUnit/Integration/SegmentTest.php
index 864420a161..19108b1312 100644
--- a/tests/PHPUnit/Integration/SegmentTest.php
+++ b/tests/PHPUnit/Integration/SegmentTest.php
@@ -458,7 +458,7 @@ class SegmentTest extends IntegrationTestCase
     }
 
 
-    public function test_getSelectQuery_whenLimit_innerQueryShouldHaveLimit()
+    public function test_getSelectQuery_whenLimit_innerQueryShouldHaveLimitAndNoGroupBy()
     {
         $select = 'sum(log_visit.visit_total_time) as sum_visit_length';
         $from = 'log_visit';
@@ -489,7 +489,6 @@ class SegmentTest extends IntegrationTestCase
                     ( log_visit.idvisit = ? )
                     AND
                     ( log_link_visit_action.custom_var_k1 = ? )
-                GROUP BY log_visit.idvisit
                 ORDER BY NULL
                 LIMIT 33
                     ) AS log_inner
-- 
GitLab