简体   繁体   中英

MySql , JOIN and Group By query is Using temporary and Filesort

I have 2 tables as below:

CREATE TABLE `ox_campaigns` (                                                       
    `campaignid` mediumint(9) NOT NULL auto_increment,                                
    `campaignname` varchar(255) NOT NULL default '',                                  
    `clientid` mediumint(9) NOT NULL default '0',                                                                                                    
    `is_deleted` tinyint(1) NOT NULL default '0',                                        
    PRIMARY KEY  (`campaignid`),                                                      
    KEY `ox_campaigns_clientid` (`clientid`)                                          
) ENGINE=MyISAM DEFAULT CHARSET=utf8  
CREATE TABLE `ox_clients` (                                   
  `clientid` mediumint(9) NOT NULL auto_increment,            
  `agencyid` mediumint(9) NOT NULL default '0',               
  `clientname` varchar(255) NOT NULL default '',                                                                
  `is_deleted` tinyint(4) NOT NULL,                           
  PRIMARY KEY  (`clientid`),                                  
  UNIQUE KEY `ox_clients_account_id` (`account_id`),          
  KEY `ox_clients_agencyid` (`agencyid`)                      
) ENGINE=MyISAM DEFAULT CHARSET=utf8              

One client can have many campaigns linked to it.

I have a list of campaignids with me, what I want is a list of distinct clientids for those campaigns.

The query that I am using is:

SELECT clients.* 
    FROM clients  
    JOIN campaigns ON clients.clientid = campaigns.clientid
    WHERE campaigns.is_deleted=0 
        AND campaignid in (2325,2395)
        AND clients.is_deleted=0 
    GROUP BY clients.clientid

The EXPLAIN output that it gives is:

+----+-------------+-----------+-------+-------------------------------+---------+--------+-------------------------------------------------------------------------------+
| id | select_type | table     | type  | possible_keys                 | key     | key_len| ref                      | rows| Extra                                        |
+----+-------------+-----------+-------+-------------------------------+---------+--------+-------------------------------------------------------------------------------+
| 1  |    SIMPLE   | campaigns | range | PRIMARY,ox_campaigns_clientid | PRIMARY | 3      |             NULL         | 2   | Using where; Using temporary; Using filesort |
| 1  |    SIMPLE   | clients   | eq_ref| PRIMARY                       | PRIMARY | 3      | openx.campaigns.clientid | 1   | Using where

Why it is using temporary and filesorting for this query?

It is using filesort because of the group by . You can prevent this by using an exists clause for what you are doing:

SELECT c.* 
FROM clients c 
WHERE EXISTS (SELECT 1
              FROM campaigns ca
              WHERE ca.clientid = c.clientid AND
                    ca.is_deleted = 0 AND
                    ca.campaignid IN (2325,2395)
             )
      AND c.is_deleted = 0;

You have an index on campaigns_clientid(clientid) , so this should use the index. A better index would be campaigns_clientid(clientid, is_deleted, campaign_id) . This index "covers" the subquery. In other words, the engine will only use the index and not have to read in the data pages for that table.

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