NEW Can use the result_mode of mysqli driver. Save memory for list count

This commit is contained in:
Laurent Destailleur 2021-08-16 22:36:30 +02:00
parent a5df1d28d7
commit 23083427e8
2 changed files with 509 additions and 511 deletions

View File

@ -517,19 +517,23 @@ $parameters = array();
$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook
$sql .= $hookmanager->resPrint; $sql .= $hookmanager->resPrint;
$sql .= $db->order($sortfield, $sortorder); // Count total nb of records
$nbtotalofrecords = '';
$nbtotalofrecords = ''; // TODO We can set and use an optimized request in $sqlforcount with no fields and no useless join to calculate nb of records
if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
/* This old method to get and count full list returns all record so use a high amount of memory. /* This old and fast method to get and count full list returns all record so use a high amount of memory.
$resql = $db->query($sql); $resql = $db->query($sql);
$nbtotalofrecords = $db->num_rows($resql); $nbtotalofrecords = $db->num_rows($resql);
*/ */
/* The new method does not consume memory on mysql (not tested on pgsql) */ /* The slow method does not consume memory on mysql (not tested on pgsql) */
$resql = $db->query($sql, 0, 'auto', 1); /*$resql = $db->query($sql, 0, 'auto', 1);
while ($db->fetch_object($resql)) { while ($db->fetch_object($resql)) {
$nbtotalofrecords++; $nbtotalofrecords++;
} }*/
/* This fast and low memory method to get and count full list converts the sql into a sql count */
$sqlforcount = preg_replace('/^SELECT[a-z0-9\._\s\(\),]+FROM/i', 'SELECT COUNT(*) as nbtotalofrecords FROM', $sql);
$resql = $db->query($sqlforcount);
$objforcount = $db->fetch_object($resql);
$nbtotalofrecords = $objforcount->nbtotalofrecords;
if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller then paging size (filtering), goto and load page 0 if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller then paging size (filtering), goto and load page 0
$page = 0; $page = 0;
$offset = 0; $offset = 0;
@ -537,10 +541,8 @@ if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
$db->free($resql); $db->free($resql);
} }
// if total of record found is smaller than limit, no need to do paging and to restart another select with limits set. // Complete request and execute it with limit
if (is_numeric($nbtotalofrecords) && ($limit > $nbtotalofrecords || empty($limit))) { $sql .= $db->order($sortfield, $sortorder);
$num = $nbtotalofrecords;
} else {
if ($limit) { if ($limit) {
$sql .= $db->plimit($limit + 1, $offset); $sql .= $db->plimit($limit + 1, $offset);
} }
@ -552,11 +554,8 @@ if (is_numeric($nbtotalofrecords) && ($limit > $nbtotalofrecords || empty($limit
} }
$num = $db->num_rows($resql); $num = $db->num_rows($resql);
}
dol_syslog("comm/action/list.php", LOG_DEBUG);
$resql = $db->query($sql);
if ($resql) {
$actionstatic = new ActionComm($db); $actionstatic = new ActionComm($db);
$societestatic = new Societe($db); $societestatic = new Societe($db);
@ -1055,9 +1054,6 @@ if ($resql) {
print '</form>'; print '</form>';
$db->free($resql); $db->free($resql);
} else {
dol_print_error($db);
}
// End of page // End of page
llxFooter(); llxFooter();

View File

@ -344,30 +344,32 @@ $sql .= $hookmanager->resPrint;
$sql = preg_replace('/,\s*$/', '', $sql); $sql = preg_replace('/,\s*$/', '', $sql);
*/ */
$sql .= $db->order($sortfield, $sortorder);
// Count total nb of records // Count total nb of records
$nbtotalofrecords = ''; $nbtotalofrecords = '';
if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
/* This old method to get and count full list returns all record so use a high amount of memory. /* This old and fast method to get and count full list returns all record so use a high amount of memory.
$resql = $db->query($sql); $resql = $db->query($sql);
$nbtotalofrecords = $db->num_rows($resql); $nbtotalofrecords = $db->num_rows($resql);
*/ */
/* The new method does not consume memory on mysql (not tested on pgsql) */ /* The slow method does not consume memory on mysql (not tested on pgsql) */
$resql = $db->query($sql, 0, 'auto', 1); /*$resql = $db->query($sql, 0, 'auto', 1);
while ($db->fetch_object($resql)) { while ($db->fetch_object($resql)) {
$nbtotalofrecords++; $nbtotalofrecords++;
} }*/
/* This fast and low memory method to get and count full list convert the sql into a sql count */
$sqlforcount = preg_replace('/^SELECT[a-z0-9\._\s\(\),]+FROM/i', 'SELECT COUNT(*) as nbtotalofrecords FROM', $sql);
$resql = $db->query($sqlforcount);
$objforcount = $db->fetch_object($resql);
$nbtotalofrecords = $objforcount->nbtotalofrecords;
if (($page * $limit) > $nbtotalofrecords) { // if total of record found is smaller than page * limit, goto and load page 0 if (($page * $limit) > $nbtotalofrecords) { // if total of record found is smaller than page * limit, goto and load page 0
$page = 0; $page = 0;
$offset = 0; $offset = 0;
} }
$db->free($resql); $db->free($resql);
} }
// if total of record found is smaller than limit, no need to do paging and to restart another select with limits set.
if (is_numeric($nbtotalofrecords) && ($limit > $nbtotalofrecords || empty($limit))) { // Complete request and execute it with limit
$num = $nbtotalofrecords; $sql .= $db->order($sortfield, $sortorder);
} else {
if ($limit) { if ($limit) {
$sql .= $db->plimit($limit + 1, $offset); $sql .= $db->plimit($limit + 1, $offset);
} }
@ -379,7 +381,7 @@ if (is_numeric($nbtotalofrecords) && ($limit > $nbtotalofrecords || empty($limit
} }
$num = $db->num_rows($resql); $num = $db->num_rows($resql);
}
// Direct jump if only one record found // Direct jump if only one record found
if ($num == 1 && !empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && $search_all && !$page) { if ($num == 1 && !empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && $search_all && !$page) {