I'm working on a query that uses four tables, comma-joined. Actually two queries, with only one simple difference. This one is fast (0.17 sec):
SELECT distinct l.listingId, l.title, l.slug, l.blurb, l.address1, l.address2, l.city, l.state, l.zip, l.recipientPhone, l.bbbLink, l.environixCertified, l.noEmail, l.serviceAreaCoords, l.dontDisplayAddress, l.latitude, l.longitude, SQRT(POWER(ABS((l.latitude * 69) - (47.611679 * 69)),2) + POWER(ABS((l.longitude * 60) - (-122.333261 * 60)),2)) AS distance
FROM listings AS l, listingsServices AS ls, listingsCities AS lc, services AS s
WHERE s.slug='mold-inspection' AND ls.serviceId=s.serviceId AND l.listingId=ls.listingId AND l.active > 0 AND ((lc.listingId=l.listingId AND lc.cityId=24001) OR (l.sourceCityId=24001)) AND l.recipientPhone IS NOT NULL
ORDER BY rand();
and this one is slow - a lot slower (4.2 sec):
SELECT distinct l.listingId, l.title, l.slug, l.blurb, l.address1, l.address2, l.city, l.state, l.zip, l.recipientPhone, l.bbbLink, l.environixCertified, l.noEmail, l.serviceAreaCoords, l.dontDisplayAddress, l.latitude, l.longitude, SQRT(POWER(ABS((l.latitude * 69) - (47.611679 * 69)),2) + POWER(ABS((l.longitude * 60) - (-122.333261 * 60)),2)) AS distance
FROM listings AS l, listingsServices AS ls, listingsCities AS lc, services AS s
WHERE s.slug='mold-inspection' AND ls.serviceId=s.serviceId AND l.listingId=ls.listingId AND l.active > 0 AND ((lc.listingId=l.listingId AND lc.cityId=24001) OR (l.sourceCityId=24001)) AND l.recipientPhone IS NULL
ORDER BY rand();
The only difference is the last parameter of the WHERE clause - we're looking for IS NULL in the slow one, and IS NOT NULL in the fast one.
All tables are indexed, at least as far as I can work it out. I ran EXPLAIN and get the same for both queries:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE l ALL PRIMARY,id active recip city NULL NULL NULL 1208 Using where; Using temporary; Using filesort
1 SIMPLE ls ref listing id service id listing id service id 5 environix_directory.l.listingId 1 Using where; Using index; Distinct
1 SIMPLE lc index listing city listing city 10 NULL 90 Using where; Using index; Distinct
1 SIMPLE s eq_ref PRIMARY,id slug PRIMARY 4 environix_directory.ls.serviceId 1 Using where; Distinct
As you can see the first "entry" is using temporary and filesort, but is also using where. Not sure how to get rid of the temporary/filesort, since I do have an index on the fields being queried.
Is there a clear reason why looking for an "is null" would slow things down so much? I know 4 seconds may not seem that slow, but I only have about 2% of my data in the table yet.
Thanks!
- Bob