HiveBrain v1.2.0
Get Started
← Back to all entries
patternphpMinor

Performance of loading fields

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
fieldsloadingperformance

Problem

I wrote a class with this function. Can I improve my code performance in the bottom of the function? I don't like the while loops!

public function loadFields(array $fields, $as_object = Config::FIELDS_AS_OBJECT) {
        $connection = $this->connection;
        $sql = "SELECT ".implode(",", $fields)." FROM ".$this->table." WHERE lang = ?";
        if (!($stmt = $connection->prepare($sql))){
            throw new MysqliPrepareException($connection);
        }
        if(!($stmt->bind_param('s',$this->lang))){
            throw new MysqliBindParamException($connection);
        }
        if(!$stmt->execute()){
            throw new MysqliExecuteException($connection);
        }
        $stmt->store_result();
        $variables = array();
        $data = array();
        $meta = $stmt->result_metadata();
        while ($field = $meta->fetch_field()) {
            $variables[] = &$data[$field->name];
        }
        call_user_func_array(array($stmt, 'bind_result'), $variables);
        $i = 0;
        while ($stmt->fetch()) {
            $array[$i] = array();
            foreach ($data as $k => $v) {
                $array[$i][$k] = $v;
            }
            $i++;
        }
        $array = (!isset($array[1]) ? $array[0] : $array);
        return ($as_object == true ? (object) $array : $array);
}

Solution

I'd imagine a $stmt->fetchAll() would be more performant than the while-loop and $stmt->fetch(). Rather than paging over an entire set of records one at a time, try returning the results from the database in-bulk. Your code is making a trip to the database with each iteration of your while loop. Your code will still look virtually identical:

$i = 0;
$r = $stmt->fetchAll();
foreach ($r as $data) {
    $array[$i] = array();
    foreach ($data as $k => $v) {
        $array[$i][$k] = $v;
    }
    $i++;
}


If you're using mysqli (native driver only), and not PDO's MySQL, you could do this:

$i = 0;
$r = $stmt->get_result();
$r = $r->fetchAll();
foreach ($r as $data) {
    $array[$i] = array();
    foreach ($data as $k => $v) {
        $array[$i][$k] = $v;
    }
    $i++;
}


You shouldn't worry about loops per se, but performance hits that you see, whether they come from loops or not. This is only possible if you're profiling your code.

Code Snippets

$i = 0;
$r = $stmt->fetchAll();
foreach ($r as $data) {
    $array[$i] = array();
    foreach ($data as $k => $v) {
        $array[$i][$k] = $v;
    }
    $i++;
}
$i = 0;
$r = $stmt->get_result();
$r = $r->fetchAll();
foreach ($r as $data) {
    $array[$i] = array();
    foreach ($data as $k => $v) {
        $array[$i][$k] = $v;
    }
    $i++;
}

Context

StackExchange Code Review Q#26126, answer score: 3

Revisions (0)

No revisions yet.