Hi everyone,
I'm undertaking the task of building a "store locator". I know one can purchase a pre-built store locator for a couple/few hundred dollars, but I'm not doing this to save money, I'm doing it to learn how.
I bought a zip code database that contains 70,467 rows of data and brought it into a MySQL database. I stripped the things I didn't need from each row, so I am left only with the following columns:
zip_id (PRIMARY), ZipCode, LatitudeRad, LongitudeRad
The lat./lon. values are in radians so they can be used with the Great Circle formula to calculate the distance between the center of two geographical regions, based on the zip codes of those regions.
I have a second database of retail store locations, which contains 78 rows. Each row has about 21 fields, such as id, store_name, several fields for the components of the address (e.g. line1, line2, area_code, phone_prefix, phone_suffix, zip), email_address, website, etc.
In summary, the code posted below gathers the zip codes (and row id's) of every record in the retail store database, and then calculates the distance, in miles, between the store zip code and the "user's" zip code. If the distance is within the specified search radius, the retail store id is added to an array for a future query of matching stores (which I haven't yet done).
This code works quite well, but I just want to ensure that it's being executed as quickly as possible. To check the 77 store locations against the zip code database, it takes almost exactly 3 seconds, which is the total execution time, not just the querying.
Dumping all of the superfluous information from the zip code database cut the execution time IMMENSELY; we're talking by a couple of minutes. I'm just wondering if anyone else sees something I can do to further reduce the execution time.
Thanks!
<?php
#<connect to the mysql database for forthcoming queries>
//set the credentials for connecting to the mysql database
$dbhostname = 'localhost';
$dbuser = 'wnf';
$dbpass = 'wnf1959';
$dbname = 'wnf';
//connect to the MySQL database with the supplied credentials
$dbconnection = mysql_connect($dbhostname, $dbuser, $dbpass)
//message to display if there's an error
or die('Connection to the database failed for the following reason: ' . mysql_error());
//select the specified database
mysql_select_db($dbname, $dbconnection)
//message to display if there's an error
or die ('The requested database could not be selected for the following reason: ' . mysql_error());
#</connect to the mysql database for forthcoming queries>
//set a long timeout because we're dealing with a huge database
set_time_limit(120);
//these values will eventually come from a form
$source_zip = '04096';
$radius = 1000;
//initialize the array of results that are within range
$within_range = array();
//query the database for the lat/long coordinates of the source zip code
$query_source = 'SELECT `LatitudeRad`, `LongitudeRad` FROM `zipcodes` WHERE `ZIPCode` = "' . $source_zip . '"';
$result_source = mysql_query($query_source);
$row_source = mysql_fetch_array($result_source);
$lat_1 = $row_source['LatitudeRad'];
$long_1 = $row_source['LongitudeRad'];
//query the database for all of the retail location zip codes
$query_all_locs = 'SELECT `id`, `zip` FROM `retailers`';
$result_all_locs = mysql_query($query_all_locs);
$row_all_locs = mysql_fetch_array($result_all_locs);
//for every row in the `retailers` table...
for ($i = 0; $i < mysql_num_rows($result_all_locs); $i++) {
$dest_zip = $row_all_locs['zip'];
$query_dest = 'SELECT `LatitudeRad`, `LongitudeRad` FROM `zipcodes` WHERE `ZIPCode` = "' . $dest_zip . '"';
$result_dest = mysql_query($query_dest);
$row_dest = mysql_fetch_array($result_dest);
$lat_2 = $row_dest['LatitudeRad'];
$long_2 = $row_dest['LongitudeRad'];
//the Great Circle formula for calculating the distance between two points on the surface of a sphere,
//that sphere being the Earth, in this case
$distance = 3963.0 * acos(sin($lat_1) * sin($lat_2) + cos($lat_1) * cos($lat_2) * cos($long_2 - $long_1));
if ($distance < $radius) {
$within_range[] = $row_all_locs['id'];
}
//increment the internal mysql result set pointer
$row_all_locs = mysql_fetch_array($result_all_locs);
}
//close the database connection
mysql_close($dbconnection);
?>