PHP, lots of queries, slow page loads... ?

Discussion in 'PHP' started by fatabbot, Oct 18, 2006.

  1. #1
    Hello,


    On a site i use heavy graphics, but also lots of queries on some pages.

    The graphics loading time is acceptable, but before a page actually starts loading sometimes takes a few seconds. (I click a link, status bar in browser says: 'waiting for...')
    The site is on virtual hosting and i'm not sure if the virtual hosting is causing this slowless or the amount of queries.
    Is there any way i can test this out and maybe tips on how to improving this speed or optimizing php and mysql queries ?
     
    fatabbot, Oct 18, 2006 IP
  2. T0PS3O

    T0PS3O Feel Good PLC

    Messages:
    13,219
    Likes Received:
    777
    Best Answers:
    0
    Trophy Points:
    0
    #2
    Take the queries and execute them in PHPMyAdmin. It will tell yuo how many seconds they take. Anything over 1 second is normally a crap query you need to optimize.

    After you ran it, there's an 'Explain' button. You'll have to read some tutorials on the net about MySQL query optimization with the help of explain. Once yuo get the hang of that (took me an hour and a half - no rocket science) you will know where to add an index, alter a table structure and which query to change.
     
    T0PS3O, Oct 18, 2006 IP
  3. fatabbot

    fatabbot Well-Known Member

    Messages:
    559
    Likes Received:
    10
    Best Answers:
    0
    Trophy Points:
    138
    #3
    Hi, i tried what you said in phpmyadmin.
    A total of 35 queries took 0.0049 seconds.
    So i guess that can't be the problem ?

    Here is the site btw:

    edit

    What else could cause the slow loadtimes ?
     
    fatabbot, Oct 18, 2006 IP
  4. T0PS3O

    T0PS3O Feel Good PLC

    Messages:
    13,219
    Likes Received:
    777
    Best Answers:
    0
    Trophy Points:
    0
    #4
    T0PS3O, Oct 18, 2006 IP
  5. coolsaint

    coolsaint Banned

    Messages:
    257
    Likes Received:
    4
    Best Answers:
    0
    Trophy Points:
    0
    #5
    Thanks TOPS30, I didn't know about NetMechanic . It has some really cool tools for webmaster. Very Helpful.
     
    coolsaint, Oct 19, 2006 IP
  6. intoex

    intoex Peon

    Messages:
    414
    Likes Received:
    7
    Best Answers:
    0
    Trophy Points:
    0
    #6
    all depends on queries types, database structure and number of tables.
    What script do yo use?
     
    intoex, Oct 19, 2006 IP
  7. pondlife

    pondlife Peon

    Messages:
    898
    Likes Received:
    18
    Best Answers:
    0
    Trophy Points:
    0
    #7
    I don't know what your queries are doing but 35 for one page sounds excessive? Is there anyway you can do fewer queries which collect more data? I've found that if you do this it works quicker ... you can parse the resultant array queries quicker than running the query again, if you see what I mean?

    Can you tell us what it is you're extracting from the database(s)?
     
    pondlife, Oct 19, 2006 IP
  8. intoex

    intoex Peon

    Messages:
    414
    Likes Received:
    7
    Best Answers:
    0
    Trophy Points:
    0
    #8
    35 queries could work faster then 1 query - depends on the query. mysql has caching feature, and if queries are simple, then results could be taken from cache
     
    intoex, Oct 19, 2006 IP
  9. fatabbot

    fatabbot Well-Known Member

    Messages:
    559
    Likes Received:
    10
    Best Answers:
    0
    Trophy Points:
    138
    #9

    It's just a page where i pull lots of data from different tables. But these are mostly simple SELECTS and COUNT queries. I don't think it can be done in less queries. But i tested them and the queries itself are pretty quick.
    So i guess it's the virtual hosting (hosted with 18 other sites on same server) that causes slow performance ?
     
    fatabbot, Oct 19, 2006 IP
  10. fatabbot

    fatabbot Well-Known Member

    Messages:
    559
    Likes Received:
    10
    Best Answers:
    0
    Trophy Points:
    138
    #10
    What do you mean "what script" ?
    Do you only work with pre-programmed scripts ? :confused:
     
    fatabbot, Oct 19, 2006 IP
  11. Chemo

    Chemo Peon

    Messages:
    146
    Likes Received:
    8
    Best Answers:
    0
    Trophy Points:
    0
    #11
    OK guys I'm going to suggest the obvious and say why not use a wrapper function for the mysql_query() call so that you can easily capture debug information?

    Let me give an example...

    First, create a basic debug mode function like this:
    
    	/**
    	 * Function to set and return debug mode
    	 * @author Bobby Easland 
    	 * @version 1.0
    	 * @return boolean   
    	 */	
    	function debugMode(){
    		switch(true){
    			case ( isset($_GET['output']) ):
    				if ( (int)$_GET['output'] == 1 ){
    					$_SESSION['output'] = (int)$_GET['output'];
    					return true;
    				} else {
    					if ( isset($_SESSION['output']) ){
    						unset($_SESSION['output']);
    					}
    					return false;
    				}
    				break;
    			case ( isset($_SESSION['output']) && $_SESSION['output'] == 1 ):
    				return true;
    				break;
    			default:
    				return false;
    				break;
    		}
    		return;
    	}
    
    PHP:
    OK...so now that you have the debugMode() function you can easily slip into and out of debug mode like this:
    • Activate -> xxxyy.com/script.php?output=1
    • Deactivate -> xxxyy.com/script.php?output=0

    The next step is to create your basic wrapper function for mysql_query(). I know that you probably encapsulate your functions just for situations like this but I'll give a short example anyway:
    
    	/*
    	 * Wrapper function for database query
    	 * @author Bobby Easland 
    	 * @version 1.0
    	 * @param string $sql Standard SQL statement
    	 * @param resource $linkID
    	 * @return mixed Returns resource on success or boolean false on failure
    	 */
    	function dbQuery($sql, $linkID){
    		if ( false !== ($resource = mysql_query($sql, $linkID)) ){
    			return $resource;
    		}
    		return false;
    	}
    
    PHP:
    You will need to refactor the wrapper function to allow capture of diagnostic data. Something like this will work:
    
    	/*
    	 * Wrapper function for database query
    	 * @author Bobby Easland 
    	 * @version 1.1
    	 * @param string $sql Standard SQL statement
    	 * @param resource $linkID
    	 * @return mixed Returns resource on success or boolean false on failure
    	 */
    	function dbQuery($sql, $linkID){
    		if ( debugMode() === true ){
    			global $debug;
    			static $increment = 0;
    			$start = explode(' ', microtime());
    		}
    		
    		if ( false !== ($resource = mysql_query($sql, $linkID)) ){
    			return $resource;
    		}
    		
    		if ( debugMode() === true ){
    			$time = number_format( array_sum( explode(' ', microtime()) ) - array_sum($start), 6, '.', ',');
    			$debug[$increment]['QUERY'] = $sql;
    			$debug[$increment]['TIME'] = $time;
    			if ( is_resource($resource) ){
    				$debug[$increment]['NUM_ROWS'] = mysql_num_rows($resource);
    			}
    			$increment++;
    		}
    
    		return false;
    	}
    
    PHP:
    With this code in place when in debug mode every query will capture basic diagnostic data. To view the captured data you simply have to do something like this near the bottom of your script:
    
    <pre>
    	<?php print_r($debug); ?>
    </pre>
    
    PHP:
    The data captured is very basic and the only meaningful metric is the time it took to execute the SQL. So, you could also add a little more advanced code and capture the EXPLAIN data provided by MySQL. Refactor the wrapper to look something like this and add another function:
    
    	/*
    	 * Wrapper function for database query
    	 * @author Bobby Easland 
    	 * @version 1.2
    	 * @param string $sql Standard SQL statement
    	 * @param resource $linkID
    	 * @return mixed Returns resource on success or boolean false on failure
    	 */
    	function dbQuery($sql, $linkID){
    		if ( debugMode() === true ){
    			global $debug;
    			static $increment = 0;
    			$start = explode(' ', microtime());
    		}
    		
    		if ( false !== ($resource = mysql_query($sql, $linkID)) ){
    			return $resource;
    		}
    		
    		if ( debugMode() === true ){
    			$time = number_format( array_sum( explode(' ', microtime()) ) - array_sum($start), 6, '.', ',');
    			$debug[$increment]['QUERY'] = $sql;
    			$debug[$increment]['TIME'] = $time;
    			if ( is_resource($resource) ){
    				$debug[$increment]['NUM_ROWS'] = mysql_num_rows($resource);
    			}
    			if ( false !== eregi("select", $sql) ){
    				$debug[$increment]['EXPLAIN'] = dbExplainQuery($sql, $linkID, $increment);
    			}
    			$increment++;
    		}
    
    		return false;
    	}
    	
    	/*
    	 * Function to retrieve MySQL Explain data
    	 * @author Bobby Easland 
    	 * @version 1.1
    	 * @param string $sql Standard SQL statement
    	 * @param resource $linkID
    	 * @param integer $increment
    	 * @return array Explain data for query
    	 */
    	function dbExplainQuery($sql, $linkID){
    		$explain = 'EXPLAIN ' . $sql;
    		$query = mysql_query($sql, $linkID);
    		$data = array();
    		if ( is_resource($query) && mysql_num_rows($query) > 0 ){
    			while($result = mysql_fetch_array($query)){
    				$data[] = $result;
    			}
    		}
    		return $data;
    	}
    
    PHP:
    With all of this implemented you should now have the tools available to fully diagnose each query on any page that is refactored to use the wrapper function.

    Enjoy!

    Bobby
     
    Chemo, Oct 21, 2006 IP
  12. fatabbot

    fatabbot Well-Known Member

    Messages:
    559
    Likes Received:
    10
    Best Answers:
    0
    Trophy Points:
    138
    #12
    great info chemo
    Thanks!
     
    fatabbot, Oct 22, 2006 IP
  13. Chemo

    Chemo Peon

    Messages:
    146
    Likes Received:
    8
    Best Answers:
    0
    Trophy Points:
    0
    #13
    Thank you...if you need any help getting it implemented or analyzing the data just post back.

    Bobby
     
    Chemo, Oct 22, 2006 IP