Search Speed: Isset vs In_array vs MySQL Query

As databases and visitors grow, sometimes ‘old code’ doesn’t work like it use to: it takes too long or times out for exceeding the maximum time allowed by your server for PHP execution. On a MySQL table with 30,000 rows (not too many), the query was checking one column for <3 and then matching a long list (10,000) of values in a second column using a long WHERE column2=’value’ clause. Here is an example of the table:

|--column1--|--column2--|
|     0     |    1234   |
|     3     |    5678   |
-------------------------

A MySQL query took a while, but didn’t time out when the list of WHERE column2=’value’ was less than 7000, but it was just overwhelmed at 10,000. Okay, fine, time to go to phase two: in_array().
There was an existing array of values for column2, so I could simply pull a list of <3 from MySQL (quick) and then loop through (foreach) each of the results and check whether they are in_array() for the original source. If they were, just save them to a brand new array that I’ll use to work further through the problem. For clarification, that means that the system should go through 10,000+ iterations and check if each value is in_array(). If you had not already guessed, this was disastrous. In_Array() is very inefficient, and if you are dealing with an array that is more than 100 or so values, you’ll quickly learn this fact. So what to do? Use isset().
Isset(), as a function, is incredibly fast. It only checks whether something exists, and is a great way to check for whether something exists in an array. However, the trick is using isset() will look at the KEYS, while in_array() will look at the VALUES. Is that problem? Not if you build the original array as [value]=>value (set the KEY and VALUE the same). Now, as long as your values are valid keys and unique, this won’t be a problem. Then, you can use a foreach loop to check whether it is found in the original array. Here is some sample code:

$array_source = array('abc'=>'abc','def'=>'def','ghi'=>'ghi');
$array_results = array('xyz','ghi');
foreach ($array_results as $v){
  if (isset($array_source[$v])){ //fast
    $result[] = $v; //if found, save it to a fresh array
  }
}

What was the final result? The query, run 6 different times for 6 different data sets, went from a total execution time exceeding 2 minutes (MySQL), to not working at all (in_array), to 0.18 seconds. Yes, less than one second! That is the power for checking whether a value is set when comparing arrays. Isset() is even faster by a notable amount when compared to array_diff().

Use isset() Instead of strlen()

This tip is courtesy of a great article, 10 Advanced PHP Tips Revisited

When referencing an array’s value via a numeric key, you follow the variable name ($variable) with the numeric index, enclosed by square brackets [5]. e.g. $variable[5] = ‘value’
However, when $variable represents a string, using the same syntax will return a string with the character at the position specified by the numeric index (0 marks the first character in the $variable string). An example:

$string = 'abcdefg';
var_dump($string[2]);

Output: string(1) “c”

Where this comes into play is when using isset() rather than strlen(). Consider the following example:

$string = 'abcdefg';
if (isset($string[5])){
  echo $string[5].' found!';
}

Output: f found!

$string = 'abcdefg';
if (isset($string[7])){
     echo $string[7].' found!';
  }else{
     echo 'No character found at position 7!';
}

Output: No character found at position 7!

This is faster than using strlen() because, “… calling a function is more expensive than using a language construct.” It’s little tricks like this that will keep your code lean and efficient. Thanks to Chris Shiflett and Sean Coates for their contributions to the referenced article.