Steven,
In your case, you query doesn't even use an index.  And you are using an
order by DESC.  Now what I would recommend is something like this, change
your query just to test this out.

SELECT p.* FROM p_cat c, p_ad p WHERE p.cat = c.id AND c.lft
 BETWEEN 4 AND 5 ORDER BY p.date DESC LIMIT 0,30;

Select * from p_cat inner join p_ad on p_cat.id = p_ad.cat and p_cat.lft = 4
Order by p_ad.date ASC limit 0,30.

Also add an index on id + lft on the p_cat table.  And you also don't have
an index on p_ad.date which is what you are trying to order by.

Sorry, I had to rewrite the query because aliases drive me insane.

Now in this case, you will see that with lft I have it set to do an exact
match, not a range which is what between will give you.  If you only were
doing between two numbers like 4,5 or 100,101, I would personally recommend
using IN.  But that's my preference.

Now with your order by, if you do the order by ASC, you won't have many if
any problems.  But you as a lot of people need to order by DESC, which mysql
doesn't support very well, at least if you use explain.  But there are work
arounds to solve the problem, if you are like me and want to have 0 slow
queries.

Donny

> -----Original Message-----
> From: Steven Ducat [mailto:[EMAIL PROTECTED]
> Sent: Sunday, April 11, 2004 5:32 PM
> To: [EMAIL PROTECTED]
> Subject: How can I avoid filesort with BETWEEN and ORDER BY
> 
> I am trying to optimize a query using both BETWEEN and ORDER BY but
> after months of reading and research I still can not get the hang of
> this. Details are as follows:
> 
> 2 Tables
> 
> CREATE TABLE `p_ad` (
>   `id` int(11) NOT NULL auto_increment,
>   `cat` mediumint(9) NOT NULL default '0',
>   `title` varchar(50) default NULL,
>   `description` text,
>   `location` varchar(50) default NULL,
>   `pcode` varchar(8) default NULL,
>   `pcode_id` smallint(4) default NULL,
>   `ph` varchar(50) default NULL,
>   `email` varchar(50) default NULL,
>   `user_id` int(11) NOT NULL default '0',
>   `date` timestamp(14) NOT NULL,
>   `price` decimal(10,2) default NULL,
>   `email_priv` tinyint(1) default '0',
>   PRIMARY KEY  (`id`),
>   KEY `cat_pc_date` (`cat`,`pcode_id`,`date`),
>   KEY `c_p_d` (`cat`,`pcode`,`date`),
>   KEY `user` (`user_id`),
>   KEY `cat_date` (`cat`,`date`)
> ) TYPE=MyISAM;
> 
> CREATE TABLE `p_cat` (
>   `id` mediumint(9) NOT NULL auto_increment,
>   `name` varchar(50) NOT NULL default '',
>   `parent` mediumint(11) default '0',
>   `lft` mediumint(11) NOT NULL default '0',
>   `rgt` mediumint(11) NOT NULL default '0',
>   PRIMARY KEY  (`id`),
>   KEY `LFT` (`lft`),
>   KEY `PARENT` (`parent`)
> ) TYPE=MyISAM;
> 
> Query as follows:
> 
> EXPLAIN SELECT p.* FROM p_cat c, p_ad p WHERE p.cat = c.id AND c.lft
> BETWEEN 4 AND 5 ORDER BY p.date DESC LIMIT 0,30;
> +-------+-------+----------------------------+------+---------+------+----
> ---+---------------------------------+
> | table | type  | possible_keys              | key  | key_len | ref  |
> rows  | Extra                           |
> +-------+-------+----------------------------+------+---------+------+----
> ---+---------------------------------+
> | p     | ALL   | cat_pc_date,c_p_d,cat_date | NULL |    NULL | NULL
> 60002 | Using temporary; Using filesort |
> | c     | range   | PRIMARY,LFT                   | LFT    |
>   3 | NULL |         1 | Using where                           |
> +-------+-------+----------------------------+------+---------+------+----
> ---+---------------------------------+
> 
> Is there any way I can get a query like this to avoid using a temporary
> table and filesort.
> 
> ??
> 
> 
> 
> 
> 
> 
> 
> --
> MySQL General Mailing List
> For list archives: http://lists.mysql.com/mysql
> To unsubscribe:
> http://lists.mysql.com/[EMAIL PROTECTED]
> 




-- 
MySQL General Mailing List
For list archives: http://lists.mysql.com/mysql
To unsubscribe:    http://lists.mysql.com/[EMAIL PROTECTED]

Reply via email to