views:

155

answers:

1

I have a mysql table with over 4 million of data; well the problem is that SOME queries WORK and SOME DON'T it depends on the search term, if the search term has a big volume of data in the table than I get the following error:

Fatal error: Allowed memory size of 1048576000 bytes exhausted (tried to allocate 75   bytes) in /home/****/public_html/Zend/Db/Statement/Pdo.php  on line 290

I currently have Zend Framework cache for metadata enabled, I have index on all the fields from that table.The site is running on a dedicated server with 2gb of ram.

I've also set memory limit to: ini_set("memory_limit","1000M");

Any other things that I can optimize?

Those are the types of query that I'm currently using:

            $do = $this->select()
              ->where('branche LIKE ?','%'.mysql_escape_string($branche).'%')
              ->order('premium DESC');  

        }


        //For name
        if(empty($branche) && empty($plz))
        {
              $do = $this->select("MATCH(`name`) AGAINST ('{$theString}') AS score")
              ->where('MATCH(`name`) AGAINST( ? IN BOOLEAN MODE)', $theString)
              ->order('premium DESC, score');           
        }

And a few other, but they are pretty much the same.

Best Regards

//LE

ZEND_PAGINATOR CODE

        $d = $firmen->doSearch($finalType,$theKeyword,$thePLZ,$theBranche,false,false,false,$theOrder);
    if ($d !== false) {
        $paginator = Zend_Paginator::factory($d);
        $paginator->setItemCountPerPage(5)
                  ->setPageRange(10)
                  ->setCurrentPageNumber($pag);

        $this->view->data = $paginator;

//MYSQL EXPLAIN RESULTS

mysql> EXPLAIN select * from `wirtscha_ksw`.`firmen` WHERE `name` LIKE '%gmbh%';ERROR  2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id:    32911
Current database: *** NONE ***

 +----+-------------+--------+------+---------------+------+---------+------+---------+-------------+
 | id | select_type | table  | type | possible_keys | key  | key_len | ref  | rows    |   Extra       |
 +----+-------------+--------+------+---------------+------+---------+------+---------+-------------+
 |  1 | SIMPLE      | firmen | ALL  | NULL          | NULL | NULL    | NULL | 3749155 |   Using where | 
 +----+-------------+--------+------+---------------+------+---------+------+---------+-   ------------+
 1 row in set (0.03 sec
+7  A: 

Do you really need to load all records at once? I'd recommend you to use LIMIT in those queries. In case you need to present the data, also consider using Zend_Paginator.

UPDATE: The approach you're taking is to pass Zend_Paginator all the results, which is overkilling with large resultsets. A more optimal approach in those cases is to pass it just the query, and it will then take care of fetching only the data that's needed to display the page (this includes counting the number of records and limiting the query to the number of results per page), e.g.:

$paginator = new Zend_Paginator(
    // $query is an instance of Zend_Db_Select
    new Zend_Paginator_Adapter_DbSelect($query);
);
$paginator->setItemCountPerPage(5)
          ->setPageRange(10)
          ->setCurrentPageNumber($pag);
nuqqsa
to paginate he would need to run a query that returns the size of the total resultset
seengee
Right, and that's already implemented in the Zend_Paginator component.
nuqqsa
Extra note: the problem is caused by trying to load ALL the data into objects. This is extremely resource consuming, so the optimization should be made by restricting the load, i.e., limiting the number of fetched results. A pagination requires first counting the total number results, thus it consists of 2 queries, yet the amount of loaded data may dramatically decrease.
nuqqsa
I'm already using Zend_Paginator
Uffo
Then try restricting your maximum limit and check whether you can remove some columns from the select statements.
nuqqsa
//ZEND_PAGINATOR code add to the main post; I need to set Zend_Paginator to *only* the required data for the X page, right now is loading ALL the data at once....Do you know how can I add that to my code?
Uffo
Now I see ... :) Please read updated answer.
nuqqsa
Well It works now, I don't get the "Fatal error: Allowed memory size of 1048576000 bytes exhausted (tried to allocate 75 bytes) in /home/****/public_html/Zend/Db/Statement/Pdo.php on line 290" anymore, but it takes a lot of time to display the results about 12-20 sec, frontend improvents are really hight, minified css, JS and so on...any other tips about speed improvements that you can give me?Best Regards
Uffo
Profile using xdebug and find bottleneck ;)
Tomáš Fejfar
Now it may turn out that is the database that needs to be optimized. Note that in MySQL when using LIKE with the % wildcard at the start of the string indexes are NOT used. Can you post the queries with the approximated amount of time they take to execute?
nuqqsa
@nuqqsa about 12 sec without metadata cache, and aprox 4 sec with metadata cache
Uffo
You may need to implement full-text search, with such an amount of data LIKE queries become inefficient. A more sophisticated solution could be incorporate a third-party search engine like Lucene/Solr.
nuqqsa