Question

following problem is giving me a headache.

I have set up my MySQL server to use "Query Chaching".

set global query_cache_size = 10000000;

it seems that my query cache works because the output of

SHOW STATUS LIKE 'Qcache%';  

is as follows

+-------------------------+----------+    
|    Variable_name        | Value    |           
+-------------------------+----------+     
| Qcache_free_blocks      | 1        |
| Qcache_free_memory      | 47223976 |
| Qcache_hits             | 6709     |                                       
| Qcache_inserts          | 2314     |                                    
| Qcache_lowmem_prunes    | 0        |                                  
| Qcache_not_cached       | 365      |                                  
| Qcache_queries_in_cache | 441      |                                   
| Qcache_total_blocks     | 960      |                                     
+-------------------------+----------+ 

but, nevertheles the following (complex query, with inner selects etc.) doesn't get cached.

It alsways takes at least 0.8 secs to retrieve the data for this query. How can I bring mysql to store the results of this query in it's cache?

I tried ot remove the inner selects but this didn't make a differnence.

SELECT p.id
   AS
   project_id,
   p.code
   AS project_code,
   p.title
   AS project_title,
   p.start_date
   AS project_start_date,
   p.end_date
   AS project_end_date,
   p.modf
   AS project_modf,
   ( p.budget * (SELECT 1 / r.VALUE
                 FROM   exchange_rates r
                 WHERE  r.class_currency_id = p.class_budget_currency_id) )
   AS
   project_budget,
   (SELECT z.txt
    FROM   sys_labels z
    WHERE  z.id = ps.value_label_id
           AND z.lng = 'en')
   AS project_status,
   (SELECT z.txt
    FROM   sys_labels z
    WHERE  z.id = ps.data_label_id
           AND z.lng = 'en')
   AS project_color,
   GROUP_CONCAT(DISTINCT pt.class_topic_id)
   AS projects_thematic_area_ids,
   u.id
   AS project_owner_id
FROM   projects AS p
   LEFT JOIN projects_thematic_areas AS pt
     ON pt.project_id = p.id
   LEFT JOIN sys_users AS u
     ON u.id = p.owner_uid
   LEFT JOIN class_data s
     ON s.id = p.class_status_id
   LEFT JOIN class_data AS ps
     ON ps.id = s.id
   LEFT JOIN sys_labels AS prdz1
     ON prdz1.id = prd.value_label_id
        AND prdz1.lng = 'en'
   LEFT JOIN sys_labels AS prdz2
     ON prdz2.id = prd.data_label_id
        AND prdz2.lng = 'en'
   LEFT JOIN projects_locations AS pl
     ON pl.project_id = p.id
   LEFT JOIN class_data AS l
     ON l.id = pl.class_location_id
   LEFT JOIN class_data AS r
     ON r._lft <= l._lft
        AND r._rgt >= l._rgt
        AND r._level = 1
        AND r.class_id = 5
   LEFT JOIN class_data AS c
     ON c._lft <= l._lft
        AND c._rgt >= l._rgt
        AND c._level = 2
        AND c.class_id = 10
   LEFT JOIN projects_donors AS pd
     ON pd.project_id = p.id
   LEFT JOIN institutions AS i
     ON pd.inst_id = i.id
   LEFT JOIN class_data AS ic
     ON ic.id = i.class_country_id
   LEFT JOIN projects_deliverables AS d
     ON d.project_id = p.id
WHERE  1 = 1
   AND p.is_del = "f"
   AND p.is_active = "t"
GROUP  BY p.id
ORDER  BY p.modf DESC,
      p.code DESC 

Any help apprechiated ....

Regards

J.

Was it helpful?

Solution

In addition to previous answers: The query cache will not be used even if the query is in there if there are changes in any of the selected tables.

But why are you joining al those tables when you are not selecting anything from them? Also you probably shouldn't sub-select anything if you can join it.

Something like this would select exactly the same:

SELECT
   p.id AS project_id,
   p.code AS project_code,
   p.title AS project_title,
   p.start_date AS project_start_date,
   p.end_date AS project_end_date,
   p.modf AS project_modf,
   p.budget * (1 / r.VALUE) AS project_budget,
   z1.txt AS project_status,
   z2.txt AS project_color,
   GROUP_CONCAT(DISTINCT pt.class_topic_id) AS projects_thematic_area_ids,
   u.id AS project_owner_id
FROM
   projects AS p
   LEFT JOIN projects_thematic_areas AS pt ON pt.project_id = p.id
   LEFT JOIN sys_users AS u ON u.id = p.owner_uid
   LEFT JOIN exchange_rates AS r ON r.class_currency_id = p.class_budget_currency_id
   LEFT JOIN class_data s ON s.id = p.class_status_id
   LEFT JOIN class_data AS ps ON ps.id = s.id
   LEFT JOIN sys_labels AS z1 ON z1.id = ps.value_label_id AND z1.lng = 'en'
   LEFT JOIN sys_labels AS z2 ON z2.id = ps.data_label_id AND z2.lng = 'en'
WHERE
   1
   AND p.is_del = "f"
   AND p.is_active = "t"
GROUP  BY
   p.id
ORDER  BY
   p.modf DESC,
   p.code DESC 

Of course you have (combined) indexes on all foreign keys, where fields and group fields. Consider using a tinyint or enum field for your boolean values. You may also want to consider not selecting that GROUP_CONCAT so you can lose the GROUP BY. And perhaps using INNER JOIN instead of LEFT JOIN if you are certain the relation exists.

OTHER TIPS

You may try SELECT SQL_CACHE ... FROM ...

A few basic things you can try:

  • Read the Query Cache Documentation to make sure you understand the basics and have setup it correctly.
  • Ideally isolate your MySQL database server so it is only running the commands you are giving it. If you cannot do this then try setting up and running tests on another machine.
  • Run a simple query and look at the Qcache_hits and Com_select status variables to determine whether the query cache is being hit or not.
  • Try your complex query and monitor the same values. If your query isn't hitting the cache then try smaller parts of it until you find out what is causing it to not get cached. If it is being cached then the issue may be due to any of the tables in the query being updated between queries which would invalidate the cached copy.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top