Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MYSQL查询速度慢,需要帮助理解索引_Mysql_Sql_Mariadb - Fatal编程技术网

MYSQL查询速度慢,需要帮助理解索引

MYSQL查询速度慢,需要帮助理解索引,mysql,sql,mariadb,Mysql,Sql,Mariadb,为了这篇文章的目的,我将我的问题简化为最纯粹的形式。 我有3张桌子:游戏、游戏标签和游戏标签地图 如果我想为每个游戏获得一张标签表,我会这样做: SELECT `games_tags_map`.`game_id` as 'game_id', GROUP_CONCAT(`games_tags_map`.`tag_id`) as 'tags' FROM `games_tags_map` LEFT JOIN `games_tags` on `games_tags`.id = `games_tags_m

为了这篇文章的目的,我将我的问题简化为最纯粹的形式。 我有3张桌子:游戏、游戏标签和游戏标签地图

如果我想为每个游戏获得一张标签表,我会这样做:

SELECT `games_tags_map`.`game_id` as 'game_id', GROUP_CONCAT(`games_tags_map`.`tag_id`) as 'tags'
FROM `games_tags_map`
LEFT JOIN `games_tags` on `games_tags`.id = `games_tags_map`.`tag_id`
GROUP BY `games_tags_map`.game_id
大约需要1毫秒

SELECT `games`.`id` AS 'id' from `games`

这需要尝试在表中的外键上使用索引(
games\u tags\u map
tag\u id
games\u tags\u map
games\u id
),并对尝试对查询进行排序的列进行索引
这将解决您的问题。

与其加入到所有游戏标签表中(这本身是可以的),不如在主游戏表中添加一个聚合列,将所有标签放在前面,这样您就不需要加入了。然后,您可以简单地添加一个触发器,每当在game_tags_map表中添加或删除标记时,它都会更新主games表。如果这只是为了向基于web的游戏网站显示,那么您就很好了。如果一个人对某种类型的游戏感兴趣,那么对game_tags_map表的查询将有助于总结该特定兴趣的列表

您每次都要查询所有游戏,因此这可能是更好的途径

首先,查看第一个查询并删除记号, 将长表名分别引为gtm和gt并使用别名, 您的查询甚至从不使用games_tags表,因为它是一个左连接 并且不使用其中的任何列

SELECT 
      gtm.game_id, 
      GROUP_CONCAT(gtm.tag_id) as tags
   FROM 
      games_tags_map gtm
         LEFT JOIN games_tags gt 
            on gtm.tag_id = gt.id
   GROUP BY 
      gtm.game_id
因此,本质上,它只是在做些什么

SELECT 
      gtm.game_id, 
      GROUP_CONCAT(gtm.tag_id) as tags
   FROM 
      games_tags_map gtm
   GROUP BY 
      gtm.game_id
除非您打算将_concat()分组以显示文字描述 表示的是ID,而不是ID本身。如果是通过ID,那么 您的第二个查询还可以删除games_tags表的左内连接

SELECT 
      g.id AS id,
      t.tags as tags
   FROM 
      games g
         LEFT JOIN ( SELECT 
                          gtm.game_id, 
                          GROUP_CONCAT(gtm.tag_id) as tags
                       FROM 
                          games_tags_map gtm
                             LEFT JOIN games_tags 
                                on gtm.tag_id = gt.id
                       GROUP BY gtm.game_id ) t 
            ON g.id = t.game_id
在上一个查询中,您需要加入以实际获取标记描述 而不是标签

SELECT 
      g.id,
      GROUP_CONCAT(DISTINCT gt.tag) AS tags
   FROM 
      games g
         LEFT JOIN games_tags_map gtm 
            ON g.id = gtm.game_id
            LEFT JOIN games_tags gt
               ON gtm.tag_id = gt.id 
   WHERE 
      g.active = 1
   GROUP BY 
      g.id
为了优化此查询,我将提供以下索引..
这将使整个查询与覆盖索引一起使用,并且可以处理 整个查询是按索引进行的,不需要转到原始的基础数据

table           index
games           ( active, id )
games_tags_map  ( game_id, tag_id )
games_tags      ( id, tag )
最后一个注意事项是,当你试图为帖子提供更多细节时,你可以 始终编辑现有帖子,添加更多详细信息,然后向用户发送评论 关于为审查提供的附加数据,并可能提供附加数据
内容/答案/回答。

还可以在game.active上添加索引。你可以看看这是不是很有效。在结果中,您可以看到它是如何工作的。如果您使用更多信息发布查询结果,我会尝试添加game_id和tag_id作为单独的索引。当我尝试两个版本的查询时,没有改进。我们能集中精力处理我提到的第一个查询吗?它耗时约100毫秒?它没有“order by”,为什么这么慢?我该如何改进它?第一个查询不是正确的方法,因为在联接中使用子查询会很慢,所以为什么不使用连续联接而使用子查询呢?另外,如果第二个查询为您提供了预期的结果,那么向要排序的字段添加索引将解决您的问题。好的,考虑到第二个查询,我已经尝试将排序字段添加为索引,但这没有任何帮助。请给出运行解释查询的输出,好吗?我考虑此路线是出于其他原因,但问题仍然存在,为什么这两个连接查询的速度明显慢于应有的速度?我确信一定有办法通过篡改表结构来优化它们。@hedgehog90,请参阅修订公告以澄清您的查询和覆盖索引。谢谢DRapp,这是一篇非常有用的文章。我最后做的是在games表上创建几个新列,比如“_tags”(我放了一个下划线前缀以提醒我这是一个自动字段),每当我向gt或gtm添加一个新标记时,它也会用所有标记文字设置此列。我以这种方式避免了许多连接和分组,这在性能上产生了巨大的差异。现在我只需要参考gt和gtm表就可以过滤带有特定标签的游戏,或者对游戏之间的相似性进行排序(带有标签和其他数据)
SELECT 
      g.id,
      GROUP_CONCAT(DISTINCT gt.tag) AS tags
   FROM 
      games g
         LEFT JOIN games_tags_map gtm 
            ON g.id = gtm.game_id
            LEFT JOIN games_tags gt
               ON gtm.tag_id = gt.id 
   WHERE 
      g.active = 1
   GROUP BY 
      g.id
table           index
games           ( active, id )
games_tags_map  ( game_id, tag_id )
games_tags      ( id, tag )