HiveBrain v1.2.0
Get Started
← Back to all entries
snippetsqlMinor

This query is choking the server. How can I improve it?

Submitted by: @import:stackexchange-dba··
0
Viewed 0 times
thiscanthechokingqueryimprovehowserver

Problem

Following query is hogging a lot of resources, as much as that the queries are getting locked down & CPU usage goes through the roof!

The MySQL Processes list shows that as the number of requests for the queries increases, the time to completion also increases... It reaches to a point where queries just lock down.

As per the web host, there is some problem in the query design, but I am unable to figure it out.

SELECT DISTINCT pet.*,ownrs.id AS ownrunique, ownrs.super,
(SELECT count(*) from comments WHERE pet.id=comments.petid) 
    AS noOfCom,
(SELECT count(*) from petfb WHERE pet.id=petfb.petid AND (feedback=1 OR feedback=100)) 
    AS newLikes,
(SELECT count(*) from petfb WHERE pet.id=petfb.petid AND (feedback=5 OR feedback=6)) 
    AS newDisLikes,
ownrs.name 
FROM pet, ownrs 
WHERE 1=1 AND pet.ownerID=ownrs.uniqueID AND catid=21
ORDER BY  date   DESC  LIMIT 0,10


EXPLAIN:

id  select_type         table       type    possible_keys   key         key_len ref                 rows    Extra
1   PRIMARY             pet         ref     catid           catid       4       const               4758    Using where; Using temporary; Using filesort
1   PRIMARY             ownrs       eq_ref  uniqueID        uniqueID    52      petdb.pet.ownerID   1   
4   DEPENDENT SUBQUERY  petfb       ref     petid,feedback  petid       4       petdb.pet.id        11      Using where
3   DEPENDENT SUBQUERY  petfb       ref     petid,feedback  petid       4       petdb.pet.id        11      Using where
2   DEPENDENT SUBQUERY  comments    ref     petid           petid       4       petdb.pet.id        1       Using index


DESCRIBES of the 4 tables (linked to avoid lengthy post).

EDIT 1

Based on Bohemian & a1ex07 replies, I am now using the following query. Everything is working OK but the noOfCom is being calculated wrongly for the pets that have >0 comments - it just equals to the total number of feedbacks from the petfb table for that particular pet, not the actual no of

Solution

First add the following indices:

ALTER TABLE pet
  ADD INDEX catid_date_index 
      (catid, date) ;

ALTER TABLE petfb
  ADD INDEX petid_feedback_index 
      (petid, feedback) ;


Then try this query:

SELECT pet.* 
     , ownrs.id AS ownrunique
     , ownrs.super

     , ( SELECT COUNT(*) 
         FROM comments 
         WHERE pet.id = comments.petid  
       ) AS noOfCom

     , ( SELECT MAX(comments.comDate)     --- Unfortunately, you need
         FROM comments                    --- 2 subqueries if you want
         WHERE pet.id = comments.petid    --- 2 results from a table
       ) AS lastCom                       --- (comments)

     , ( SELECT COUNT(*) 
         FROM petfb 
         WHERE pet.id = petfb.petid 
           AND feedback IN (1, 100) 
       ) AS newLikes

     , ( SELECT COUNT(*) 
         FROM petfb 
         WHERE pet.id = petfb.petid 
           AND feedback IN (5,10)  
       ) AS newDisLikes

     , ownrs.name 
FROM 
        ( SELECT pet.*
          FROM pet
          WHERE catid = 21
          ORDER BY `date` DESC 
          LIMIT 0, 10
        ) AS pet
    INNER JOIN 
        ownrs
            ON ownrs.uniqueID = pet.ownerID 
ORDER BY p.date ;

Code Snippets

ALTER TABLE pet
  ADD INDEX catid_date_index 
      (catid, date) ;

ALTER TABLE petfb
  ADD INDEX petid_feedback_index 
      (petid, feedback) ;
SELECT pet.* 
     , ownrs.id AS ownrunique
     , ownrs.super

     , ( SELECT COUNT(*) 
         FROM comments 
         WHERE pet.id = comments.petid  
       ) AS noOfCom

     , ( SELECT MAX(comments.comDate)     --- Unfortunately, you need
         FROM comments                    --- 2 subqueries if you want
         WHERE pet.id = comments.petid    --- 2 results from a table
       ) AS lastCom                       --- (comments)

     , ( SELECT COUNT(*) 
         FROM petfb 
         WHERE pet.id = petfb.petid 
           AND feedback IN (1, 100) 
       ) AS newLikes

     , ( SELECT COUNT(*) 
         FROM petfb 
         WHERE pet.id = petfb.petid 
           AND feedback IN (5,10)  
       ) AS newDisLikes

     , ownrs.name 
FROM 
        ( SELECT pet.*
          FROM pet
          WHERE catid = 21
          ORDER BY `date` DESC 
          LIMIT 0, 10
        ) AS pet
    INNER JOIN 
        ownrs
            ON ownrs.uniqueID = pet.ownerID 
ORDER BY p.date ;

Context

StackExchange Database Administrators Q#19390, answer score: 2

Revisions (0)

No revisions yet.