Zabs
Zabs

Reputation: 14142

Optimising MYSQL queries

I have a legacy PHP application (uses no framework) - in places it has some real slowdown with some queries taking 8-10 seconds.

Below is the extract from one of these slow queries I can see that I am getting filesort which indicates that this is running slow for the reason (or at least I presume) - can anyone suggest how to optimize my queries to prevent using filesort? The table has around 600,000 rows (so its fairly large)

Schema added:
(MailList_Tags)
Field   Type    Null    Key Default Extra
MailListID  int(11)     PRI 0    
Tag varchar(60)     PRI      

(MailList)    
Field   Type    Null    Key Default Extra
MailListID  int(11)     PRI NULL    auto_increment
GroupID varchar(8)  YES     NULL     
HotelID varchar(8)  YES     NULL     
Title   varchar(20) YES     NULL     
FirstName   blob    YES     NULL     
LastName    blob    YES     NULL     
CompanyName varchar(200)    YES     NULL     
Address blob    YES     NULL     
Postcode    varchar(12) YES     NULL     
Country varchar(200)    YES     NULL     
Tel varchar(40) YES     NULL     
Fax varchar(40) YES     NULL     
Email   blob                 
md5digest   varchar(32)     UNI      
Sub1    int(1)      MUL 0    
Sub2    int(1)      MUL 0    
Sub3    int(1)      MUL 0    
OptInState  char(1)     MUL P    
UpdateDetailsState  char(1) YES     NULL     
Bounce  int(11)         0


EXPLAIN SELECT  `Tag` , COUNT( DISTINCT (
`MailList_Tags`.`MailListID`
) ) AS  `Count` 
FROM  `MailList` 
JOIN  `MailList_Tags` ON  `MailList`.`MailListID` =  `MailList_Tags`.`MailListID` 
WHERE HotelID =  'ca4b9ac9'
AND OptInState =  'V'
GROUP BY  `Tag`

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  MailList_Tags   index   MailListID  MailListID  64  NULL    962583  Using index; Using filesort
1   SIMPLE  MailList    eq_ref  PRIMARY,OptInState  PRIMARY 4   user_db.MailList_Tags.MailListID    1   Using where

Upvotes: 0

Views: 72

Answers (1)

ypercubeᵀᴹ
ypercubeᵀᴹ

Reputation: 115630

You need some indexes:

  • on table MailList_Tags, add a UNIQUE index on (Tag, MailListID)

  • on table MailList, add an index on (OptInState, HotelID, MailListID).

Then try this query (changed COUNT( DISTINCT MailList_Tags.MailListID ) to COUNT(*), should produce the same result):

SELECT  Tag 
     ,  COUNT( * )
          AS  `Count` 
FROM  MailList 
  JOIN  MailList_Tags 
    ON  MailList.MailListID = MailList_Tags.MailListID 
WHERE  HotelID =  'ca4b9ac9'
  AND  OptInState =  'V'
GROUP BY  Tag

or this one:

SELECT  Tag 
     ,  COUNT(*)
          AS  `Count` 
FROM  MailList 
WHERE  EXISTS 
       ( SELECT  *
         FROM  MailList_Tags 
         WHERE  MailList.MailListID = MailList_Tags.MailListID 
           AND  HotelID =  'ca4b9ac9'
           AND  OptInState =  'V'
       )
GROUP BY  Tag

Upvotes: 1

Related Questions