Hi,
I've a huge (4Go) database with 157 302 nodes and more than 1.5 million comments when the views module try to execute the query below it takes 22s to MySQL to return the result, do you have any MySQL or Drupal trick to help me reduce this time? (without using drupal cache)
I'm running this website on a Intel Xeon Quad Core 3220/3330 dedicated server with 8go of memory
SELECT DISTINCT node.nid AS nid,
votingapi_cache_node_points_vote_positives.value AS votingapi_cache_node_points_vote_positives_value,
node.created AS node_created,
users.picture AS users_picture,
users.uid AS users_uid,
users.name AS users_name,
users.mail AS users_mail,
node.title AS node_title,
node.language AS node_language,
node_revisions.body AS node_revisions_body,
node_revisions.format AS node_revisions_format,
node_comment_statistics.comment_count AS node_comment_statistics_comment_count,
node.vid AS node_vid
FROM node node
INNER JOIN users users ON node.uid = users.uid
LEFT JOIN votingapi_cache votingapi_cache_node_points_vote_positives ON node.nid = votingapi_cache_node_points_vote_positives.content_id AND (votingapi_cache_node_points_vote_positives.content_type = 'node' AND votingapi_cache_node_points_vote_positives.value_type = 'points' AND votingapi_cache_node_points_vote_positives.tag = 'vote' AND votingapi_cache_node_points_vote_positives.function = 'positives')
LEFT JOIN node_revisions node_revisions ON node.vid = node_revisions.vid
INNER JOIN node_comment_statistics node_comment_statistics ON node.nid = node_comment_statistics.nid
WHERE (node.status <> 0) AND (node.type in ('poll', 'dua', 'link', 'photo', 'quote', 'text', 'video'))
ORDER BY node_created DESC
LIMIT 0, 50;

Comments
MySQL EXPLAIN + collation
What does the MySQL EXPLAIN command gives you on this query? Are the joined tables all using the same collation?
Benoit Borrel
MySQL Explain give me the
MySQL Explain give me the following result (sorry for the formatting):
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE node_comment_statistics ALL PRIMARY NULL NULL NULL 157302 Using temporary; Using filesort
1 SIMPLE node eq_ref PRIMARY,node_status_type,node_type,uid PRIMARY 4 mejliss.node_comment_statistics.nid 1 Using where
1 SIMPLE votingapi_cache_node_points_vote_positives ref content,content_function,content_tag_func,content_... content_vtype_tag_func 780 const,mejliss.node.nid,const,const,const 1
1 SIMPLE node_revisions eq_ref PRIMARY PRIMARY 4 mejliss.node.vid 1
1 SIMPLE users eq_ref PRIMARY PRIMARY 4 mejliss.node.uid 1 Using where
Alakees
Développement drupal / open source
36 avenue du Général de Gaulle
93130 Bagnolet
Using temporary; Using filesort
Sorting on 157302 rows without an index appears to be the problem. The temporary table will only be dumped to disk if temp tables are too small in MySQL config. Given your very slow times this is probably happening. dbtuner could be handy here again to diagnose if the disk is being used. Increasing temp file sizes this may keep the query in RAM but given that you have 150K rows there it will remain on the slowish side. However, given the output of the explain I can't work out why this is... sorry. It says that it can use the PRIMARY nid as an index which should work.
It's possible that the DISTINCT is causing problems. You probably can remove it as all of the joins are going out to pick up only one row. I can't see that the results would change by removing it. Give that a try. That's an option in views IIRC. Turning that off may allow the index to be used.
One last guess for you - the "ORDER BY node.created" could probably be replaced by "ORDER BY node.nid". This could help you get some reuse out of the node.nid index rather than doing a sort on created.
Hopefully one of these suggestions will work. I'll quit now while I'm only slightly behind...
Managing Director
Morpht
A couple of things
One possible area of slowness is with the votingapi_cache table. It has a design which is a little unusual since it requires a whole bunch of AND clauses to pick out the row you need. This isn't a problem so long as the multiple col indexes on that table are working for you. When I was faced with a similar problem (lots of nodes with ratings) I had to add another multi col index IIRC to get the query to work well. The end result is a table with a lot of duplication in the indexes but it can be made to work. Running MySQL EXPLAIN will tell you if an index is being picked up or not.
The LEFT JOIN to votingapi_cache may well be slower than an INNER JOIN. If you don't mind missing out on rows with no ratings then this could be an option.
Research hook_views_pre_execute to find out how to tweak the SQL before the sql is run.
Make sure all of your indexes are fitting into RAM. The dbtuner module is good for checking that you have RAM allocated correctly. I'd guess that most of that 8G is going to be needed.
Managing Director
Morpht
Index Hints
I just posted on my blog about a similar problem I had a couple months ago. For some reason my client's version of MySQL (5.0, I think) was not choosing the most effective index for the query. I played with indexes for a while, then discovered a feature of MySQL called Index Hints. Try rewriting the FROM portion of your posted query to look like this:
FROM node node USE INDEX (node_created)The node_created index will be the most efficient since you are sorting by that. If that doesn't work, play around with other index suggestions.
If that speeds up your query significantly and gets rid of your filesort, then you might want to use the module I created to allow you to add MySQL index hint syntax to a Views query.
You can read more about my situation and find the module I wrote at the following link:
http://nathan.rambeck.org/blog/32-views-index-hint-module
--
Nathan Rambeck