为大表放置什么SQL索引

时间:2014-09-09 07:55:18

标签: mysql sql indexing query-optimization

我有两个大表,我主要从中选择,但有2个连接的复杂查询非常慢。

第一个表是GameHistory,我在其中存储每个完成游戏的记录(我在单独的表中有15个游戏)。 字段:id,date_end,game_id,..

第二个表是GameHistoryParticipants,其中我存储了参与特定游戏的每个玩家的记录。 字段:player_id,history_id,is_winner

今天获得顶级球员的查询非常缓慢(20秒以上)。 查询:

SELECT p.nickname, count(ghp.player_id) as num_games_today  
FROM `GameHistory` as gh 
INNER JOIN GameHistoryParticipants as ghp ON gh.id=ghp.history_id    

INNER JOIN Players as p ON p.id=ghp.player_id     

WHERE TIMESTAMPDIFF(DAY, gh.date_end, NOW())=0 AND gh.game_id='scrabble' 

GROUP BY ghp.player_id ORDER BY count(ghp.player_id) DESC LIMIT 10

第一张表有150万条记录,第二张表有350万条记录。 我应该放什么指数? (我尝试了一些而且一切都很慢)

2 个答案:

答案 0 :(得分:1)

您只对今天的记录感兴趣。但是,您使用TIMESTAMPDIFF搜索整个GameHistory表以检测这些记录。即使您在该列上有索引,也不能使用它,因为您在该字段上使用了一个函数。

你应该在game_id和date_end两个字段都有一个索引。然后直接询问date_end值:

WHERE gh.date_end >= DATE(NOW())
AND gh.date_end < DATE_ADD(DATE(NOW()), INTERVAL 1 DAY)
AND gh.game_id = 'scrabble' 

在date_end&#39; 日期部分上设置索引,而不是在整个时间内携带date_end更好。但是,这在MySQL中是不可能的。因此,请考虑仅为日期部分添加另一列trunc_date_end,您将使用插入前触发器填充该列。然后你在trunc_date_end和game_id上​​有一个索引,它可以帮助你立刻找到所需的记录。

WHERE gh.trunc_date_end = DATE(NOW())
AND gh.game_id = 'scrabble' 

答案 1 :(得分:0)

在查询开头添加'EXPLAIN'命令,然后在数据库查看器中运行它(例如:sqlyog),您将看到有关查询的详细信息,查找'rows'列,您将看到不同的整数值。现在,索引EXPLAIN命令结果中指示的包含大行的表列。

- 我认为我的解释有点混乱,你可以要求澄清