On Nov 12, 2007 7:57 AM, Stut <[EMAIL PROTECTED]> wrote:
> Hi Rob,
>
> Thanks for your reply.
>
>
> Rob Wultsch wrote:
> > On Nov 8, 2007 4:08 PM, Stut <[EMAIL PROTECTED]> wrote:
> >> Hi all,
> >>
> >> I've inherited a PHP app that uses a MySQL database. The following query
> >> is extremely slow and I've been battling for a couple of days on an off
> >> to try and get a combination of indexes to optimise it. Any help would
> >> be greatly appreciated.
> >>
> >>
> >> select household_d.id, household_d.ad_type, household_d.ad_catid,
> >>         household_d.ad_renewed, household_d.ad_userid,
> >>         household_d.ad_trade, household_d.price,
> >>         SUBSTRING(household_d.description, 1, 301) as description,
> >>         users.issuperseller, users.phone, users.town
> >> from household_d
> >> left join users on household_d.ad_userid = users.id
> >> where household_d.ad_catid in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
> >>    and household_d.ad_status = "live"
> >>    and household_d.id not in (1, 2)
> >> order by ad_renewed desc
> >> limit 0,14
> >>
> >>
> >> Explain currently states that it's using the primary key for the users
> >> table, and the following for the household_d table...
> >>
> >> select_type = SIMPLE
> >> type = ref
> >> key = ad_status
> >> ref = const
> >> key_len = 1
> >> key_len
> >> rows = 22137
> >> extra = Using where; Using filesort
> >>
> >> Running locally this query is pretty fast, but on the live site it is
> >> currently taking anything up to a minute. My limited knowledge of MySQL
> >> indexes led me to add an index with ad_catid, ad_status, ad_renewed and
> >> id, but explain only says it's a possible key, it doesn't actually use it.
> >>
> >> Any tips appreciated.
> >
> > A few things pop out at me:
> > 1. Mysql is known for not dealing with 'IN(' or 'OR' queries particulary 
> > well.
> >         Could you instead do something like:
> >         where household_d.ad_catid BETWEEN 1 AND 10
> >         ?
> > 1.1 Same deal with household_d.id
>
> Unfortunately not. Neither ad_catid nor id are sequential.
>
> > 2. I am going to guess that ad_status has very low cardinality. I
> > generally build up composite index's by creating an index on whatever
> > column I think would have the highest useful cardinality. I then test
> > it to make sure mysql actually uses the new index. If it does not I
> > figure out why. I then add another column to the index and test the
> > query to make sure extra length gets used and the query did not get
> > slower. Rinse, wipe, repeat.
>
> That's basically what I was doing, but I wasn't getting anywhere. Since
> I posted the question I've thrown more RAM at the server and it's a lot
> better now but I still worry that it's using where and filesort but it's
> possible there's no way to make it any quicker. I've not had any
> complaints about the speed since I put more RAM in.
>
> Thanks again.
>
> -Stut
>
If you have to deal with it again consider using a bunch of unions
instead of the 'IN'. Not prettiest thing, but it should fix your
performance issue.

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

Reply via email to