在执行子查询时进行全表扫描

时间:2015-04-15 10:47:38

标签: mysql sql

我有一个非常简单的查询来获得一个玩家和他的朋友,但它似乎做了一个全表扫描,我没有看到它的原因。我是否需要将其重写为连接以使其使用索引?播放器表有7411行。

SQL:

SELECT id, credits, name, image_url FROM player WHERE ID = '999'  
or ID in(select friend_id from player_friends where player_id = '999')

解释:

'1','PRIMARY','player','ALL','PRIMARY',NULL,NULL,NULL,'6994','Using where'
'2','DEPENDENT SUBQUERY','player_friends','ref','index2','index2','198','const,func','1','Using where; Using index'

架构:

CREATE TABLE `player` (
`ID` varchar(32) NOT NULL,
`Name` varchar(45) DEFAULT NULL,
`Credits` decimal(12,3) DEFAULT NULL,
`Access_token` varchar(255) DEFAULT NULL,
`Registered` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`Image_url` varchar(500) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8$$


CREATE TABLE `player_friends` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
`player_id` varchar(32) DEFAULT NULL,
`friend_id` varchar(32) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `index2` (`player_id`,`friend_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8$$

2 个答案:

答案 0 :(得分:1)

首先,编写查询以使用exists

SELECT id, credits, name, image_url
FROM player p
WHERE ID = '999' OR
      EXISTS (select 1
              from player_friends pf
              where pf.player_id = '999' and pf.friend_id = p.id
             );

这可能会更有效率。如果它不能满足您的需求,请考虑将其分为两个查询:

SELECT id, credits, name, image_url
FROM player p
WHERE ID = '999' 
UNION
SELECT id, credits, name, image_url
FROM player p
WHERE EXISTS (select 1
              from player_friends pf
              where pf.player_id = '999' and pf.friend_id = p.id
             );

请注意使用UNION删除重复项。

答案 1 :(得分:0)

尝试加入:

SELECT p1.id, p1.credits, p1.name, p1.image_url 
FROM player p1
LEFT JOIN player_friends pf ON pf.player_id = p1.id
WHERE p1.id = '999' OR pf.friend_id = '999'