简体   繁体   中英

How can i optimize my sql query?

I have a problem. I have a sql query. query is so slow when i use order by distance. But if i dont use order by distance then query is fast. My query is:

SELECT     id,groupname,lat,lon,is_public,firma_kat,title,
           ((ACOS(SIN(41.06775100000000 * PI() / 180) * SIN(lat * PI() / 180) + 
           COS(41.06775100000000 * PI() / 180) * COS(lat * PI() / 180) * 
           COS((29.00661300000000 - lon) * PI() / 180)) * 180 / PI()) * 60 * 1.1515) 
           AS distance 
FROM       `groups` 
WHERE      id NOT IN(222330, 14302, 178547, 178563, 178572, 178571, 178573, 222328, 
                     222334, 222342, 222358, 222366, 222370, 222371, 222373, 222383, 
                     222384, 222396, 222419, 222438, 222539, 222553, 222555, 222563, 
                     222565, 222572, 222574, 222575, 222576, 222577, 222579, 222591, 
                     222592, 222594, 222613, 222711, 222630, 222632, 222653, 222657, 
                     222677, 222679, 222683, 222688, 222689, 222697, 222719, 222721, 
                     222727, 222728, 222735, 222736, 222737, 222744, 222746, 222749, 
                     222770, 222771, 222791, 222797, 222798, 222803, 222800, 222801, 
                     222802, 222804, 222805, 222806, 222807, 222808) 
HAVING     distance <= '100' 
ORDER BY   distance ASC LIMIT 0,50

Is there an alternative query for this query. Thank you.

It's your use of HAVING instead of a WHERE contraint. Your construct is syntactically equivalent of:

SELECT * FROM (
    SELECT     id,groupname,lat,lon,is_public,firma_kat,title,
               ((ACOS(SIN(41.06775100000000 * PI() / 180) * SIN(lat * PI() / 180) + 
               COS(41.06775100000000 * PI() / 180) * COS(lat * PI() / 180) * 
               COS((29.00661300000000 - lon) * PI() / 180)) * 180 / PI()) * 60 * 1.1515) 
               AS distance 
    FROM       `groups` 
    WHERE      id NOT IN(222330, 14302, 178547, 178563, 178572, 178571, 178573, 222328, 
                         222334, 222342, 222358, 222366, 222370, 222371, 222373, 222383, 
                         222384, 222396, 222419, 222438, 222539, 222553, 222555, 222563, 
                         222565, 222572, 222574, 222575, 222576, 222577, 222579, 222591, 
                         222592, 222594, 222613, 222711, 222630, 222632, 222653, 222657, 
                         222677, 222679, 222683, 222688, 222689, 222697, 222719, 222721, 
                         222727, 222728, 222735, 222736, 222737, 222744, 222746, 222749, 
                         222770, 222771, 222791, 222797, 222798, 222803, 222800, 222801, 
                         222802, 222804, 222805, 222806, 222807, 222808) 
) AS grp
WHERE grp.distance <= '100' 
ORDER BY grp.distance ASC LIMIT 0,50

Now do you see why it can run a lot slower?

Addendum

Something like:

SELECT     id,groupname,lat,lon,is_public,firma_kat,title,
           ((ACOS(SIN(41.06775100000000 * PI() / 180) * SIN(lat * PI() / 180) + 
           COS(41.06775100000000 * PI() / 180) * COS(lat * PI() / 180) * 
           COS((29.00661300000000 - lon) * PI() / 180)) * 180 / PI()) * 60 * 1.1515) 
              AS distance 
FROM       `groups` 
WHERE      id NOT IN(222330, 14302, 178547, 178563, 178572, 178571, 178573, 222328, 
                     222334, 222342, 222358, 222366, 222370, 222371, 222373, 222383, 
                     222384, 222396, 222419, 222438, 222539, 222553, 222555, 222563, 
                     222565, 222572, 222574, 222575, 222576, 222577, 222579, 222591, 
                     222592, 222594, 222613, 222711, 222630, 222632, 222653, 222657, 
                     222677, 222679, 222683, 222688, 222689, 222697, 222719, 222721, 
                     222727, 222728, 222735, 222736, 222737, 222744, 222746, 222749, 
                     222770, 222771, 222791, 222797, 222798, 222803, 222800, 222801, 
                     222802, 222804, 222805, 222806, 222807, 222808) 
WHERE 
  long BETWEEN AAAA AND BBBB AND
  lat  BETWEEN BBBB AND DDDD AND
  distance <= '100' 
ORDER distance ASC LIMIT 0,50

if you precompute the AAAA ... DDDD to be the bounding rectangle and you have non-unique indexes on lat and long. This will at least limit the rows to be read as well as those to be sorted

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM