Skip to content

Commit d6927f9

Browse files
Optimize count queries by removing all joins if there are no where clauses using joined tables and all joins are left joins (#2210)
1 parent 12aab25 commit d6927f9

File tree

1 file changed

+25
-0
lines changed
  • lib/Varien/Data/Collection

1 file changed

+25
-0
lines changed

lib/Varien/Data/Collection/Db.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,32 @@ public function getSelectCountSql()
239239
$countSelect->columns("COUNT(DISTINCT " . implode(", ", $group) . ")");
240240
} else {
241241
$countSelect->columns('COUNT(*)');
242+
243+
// Simple optimization - remove all joins if there are no where clauses using joined tables and all joins are left joins
244+
$leftJoins = array_filter($countSelect->getPart(Zend_Db_Select::FROM), function($table) {
245+
return ($table['joinType'] == Zend_Db_Select::LEFT_JOIN || $table['joinType'] == Zend_Db_Select::FROM);
246+
});
247+
if (count($leftJoins) == count($countSelect->getPart(Zend_Db_Select::FROM))) {
248+
$mainTable = array_filter($leftJoins, function ($table) {
249+
return $table['joinType'] == Zend_Db_Select::FROM;
250+
});
251+
$mainTable = key($mainTable);
252+
$mainTable = preg_quote($mainTable, '/');
253+
$pattern = "/^$mainTable\\.\\w+/";
254+
$whereUsingJoin = array_filter($countSelect->getPart(Zend_Db_Select::WHERE), function ($clause) use ($pattern) {
255+
$clauses = preg_split('/(^|\s+)(AND|OR)\s+/', $clause, -1, PREG_SPLIT_NO_EMPTY);
256+
return array_filter($clauses, function ($clause) use ($pattern) {
257+
$clause = preg_replace('/[()`\s]+/', '', $clause);
258+
return !preg_match($pattern, $clause);
259+
});
260+
});
261+
if (empty($whereUsingJoin)) {
262+
$from = array_slice($leftJoins, 0, 1);
263+
$countSelect->setPart(Zend_Db_Select::FROM, $from);
264+
}
265+
}
242266
}
267+
243268
return $countSelect;
244269
}
245270

0 commit comments

Comments
 (0)