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.