Sebastian <[EMAIL PROTECTED]> wrote on 08/11/2005 01:19:30 PM:

> well i managed to solve the problem myself, and im no sql genius...
> i thought i had an index on maps_rating.map which i didn't.. adding an 
> index on it improved the query.
> 
> i think that is about all the improvement i can get.. but if there is 
> still room for more speed i'd like to know..
> 
> Sebastian wrote:
> 
> > Jigal van Hemert wrote:
> >
> >> Sebastian wrote:
> >>
> >>> this query runs slow because AVG and COUNT on maps_rating table i 
> >>> think.
> >>> can anything be done to improve?
> >>
> >>
> >>
> >> You may want to include:
> >> - table definitions (output of SHOW CREATE TABLE <table>)
> >> - output of EXPLAIN <query>
> >
> >
> > sorry for the lack of info.
> > there are a couple of indexes on maps table, but i am not using them 
> > unless i use a where clause.
> >
> > not sure if the format is going to appear correctly on mailing list 
> > email, here is the info:
> >
> > id     select_type     table     type     possible_keys     key 
> > key_len     ref     rows     Extra
> > 1     SIMPLE     maps     ALL     /NULL/     /NULL/     /NULL/ 
> > /NULL/     626     Using temporary; Using filesort
> > 1     SIMPLE     maps_rating     ALL     /NULL/     /NULL/ 
> > /NULL/     /NULL/     1839      1     SIMPLE     user     eq_ref 
> > PRIMARY     PRIMARY     4     site.maps.userid     1 
> >
> > CREATE TABLE `maps` (
> >  `id` int(10) unsigned NOT NULL auto_increment,
> >  `mip` smallint(6) NOT NULL default '0',
> >  `map` varchar(50) NOT NULL default '',
> >  `userid` int(10) unsigned NOT NULL default '0',
> >  `filename` varchar(50) NOT NULL default '',
> >  `date` int(10) unsigned NOT NULL default '0',
> >  PRIMARY KEY  (`id`),
> >  KEY `mip` (`mip`)
> > ) ENGINE=MyISAM DEFAULT CHARSET=latin1 PACK_KEYS=0 AUTO_INCREMENT=740;
> >
> > CREATE TABLE `maps_rating` (
> >  `id` int(10) unsigned NOT NULL auto_increment,
> >  `map` int(10) NOT NULL default '0',
> >  `rating` smallint(6) NOT NULL default '0',
> >  `userid` int(10) unsigned NOT NULL default '0',
> >  `ipaddress` varchar(15) NOT NULL default '',
> >  `dateline` int(10) unsigned NOT NULL default '0',
> >  PRIMARY KEY  (`id`)
> > ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1884;
> >
> > the query:
> >
> > SELECT
> > maps.*, AVG(maps_rating.rating) AS rating, COUNT(maps_rating.id) AS 
> > votes, user.username
> > FROM maps
> > LEFT JOIN maps_rating ON (maps.id = maps_rating.map)
> > LEFT JOIN user ON (user.userid = maps.userid)
> > GROUP BY maps.id ORDER BY maps.dateline DESC LIMIT $start, $perpage
> >
> 

This is not to solve your problem (you already did that) but to respond to 
your request for possible additional optimizations.

One of the basic principles I try to use when optimizing is to JOIN as 
little data as possible, even if it takes more than one step. What your 
original query does is to JOIN three tables then GROUP BY on the resulting 
combinations of records. If you eliminated all of the duplication from 
your secondary tables (maps_rating and user) by performing your AVG and 
COUNT in separate steps, you reduce the amount of data you need to 
reprocess through the GROUP BY by an order of magnitude. Less data = less 
time.

Here is how I would approach your problem. I would create a temp table (or 
a static table if you run this often enough) that contains whatever 
statistics you want (your COUNTs, AVGs, etc.) then join that to the `maps` 
table to fill in the rest of the columns you wanted in your report. The 
whole query would resemble something like this:

CREATE TEMPORARY TABLE tmpRatings(KEY(map))
SELECT map
        , avg(rating) as rating
        , count(id) as votes
FROM maps_rating
GROUP BY map;

SELECT
maps.*, AVG(maps_rating.rating) AS rating, COUNT(maps_rating.id) AS 
votes, user.username
FROM maps
LEFT JOIN user ON (user.userid = maps.userid)
LEFT JOIN tmpRatings ON tmpRatings.map = maps.id
ORDER BY maps.dateline DESC 
LIMIT $start, $perpage;

Assuming an average of 10 ratings per map, you save at least 10x the 
processing time in your final query as compared to your original. We did 
add a little processing to create the statistics table, however the 
additional overhead is not nearly as much as we saved so the net gain will 
still be quite noticeable.

Please give it a shot and let me know how it compares to your original. 
Thanks.

Shawn Green
Database Administrator
Unimin Corporation - Spruce Pine











Reply via email to