MySql、JOIN和Group By query正在使用临时和文件排序

MySql、JOIN和Group By query正在使用临时和文件排序,mysql,join,explain,Mysql,Join,Explain,我有以下两个表格: 创建表格ox\u活动( activitidmediumint(9)非空自动增量, campaignamevarchar(255)非空默认值“”, clientidmediumint(9)不为空默认值“0”, 已删除tinyint(1)不为空默认值“0”, 主键(活动ID), 按键ox\u活动\u客户端ID(clientid) )ENGINE=MyISAM默认字符集=utf8 创建表ox\u客户端( clientidmediumint(9)非空自动增量, agencyidmed

我有以下两个表格:

创建表格
ox\u活动

activitid
mediumint(9)非空自动增量,
campaigname
varchar(255)非空默认值“”,
clientid
mediumint(9)不为空默认值“0”,
已删除
tinyint(1)不为空默认值“0”,
主键(
活动ID
),
按键
ox\u活动\u客户端ID
clientid

)ENGINE=MyISAM默认字符集=utf8

创建表
ox\u客户端

clientid
mediumint(9)非空自动增量,
agencyid
mediumint(9)不为空默认值“0”,
clientname
varchar(255)非空默认值“”,
已删除
tinyint(4)不为空,
主键(
clientid
),
唯一键
ox\u客户\账户\ id
账户\ id
),
ox\u客户端\u代理ID
agencyid

)ENGINE=MyISAM默认字符集=utf8

一个客户端可以有多个活动链接到它

我有一个活动ID列表,我想要的是这些活动的不同客户ID列表

我使用的查询是:

SELECT clients.* 
    FROM 
        clients clients  
    JOIN 
        campaigns 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
它给出的解释输出是:

    +----+-------------+-----------+--------+-------------------------------+------+--------------------------------------------------------------------------------------------------------------------
    | 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

为什么要对此查询使用临时和文件排序?

它之所以使用文件排序,是因为
group by
。您可以使用
exists
子句来防止这种情况:

SELECT clients.* 
FROM clients clients  
WHERE exists (select 1
              from campaigns
              where clients.clientid = campaigns.clientid and
                    campaigns.is_deleted = 0 and
                    campaignid in (2325,2395)
             ) and
      clients.is_deleted = 0 ;

您在
活动\u clientid(clientid)
上有一个索引,因此应该使用该索引。更好的索引应该是
活动\u clientid(clientid,is\u deleted,campaign\u id)
。此索引“覆盖”子查询。换句话说,引擎将只使用索引,而不必读取该表的数据页。

分组依据是什么?@草莓,实际上一个客户端可以链接多个活动,我只需要相应活动ID的不同客户端信息。请使用distinct。在某些情况下,分组将产生意外的结果。尽管MySQL允许此活动,但在没有任何聚合函数的情况下不应使用GROUPBY。请注意,这不是性能问题。@debaShish如果您认为答案正确,请将其标记为正确。