如何使这个多连接MySQL查询更清洁/具有更好的性能?

时间:2013-01-04 16:20:49

标签: mysql

我正在尝试为我正在制作的网站构建搜索查询,以构建最近/在线玩家列表,他们正在玩或想玩的游戏,他们正在玩哪个平台,如果他们有一个麦克风,他们的平台游戏者标签/图像以及他们想要玩的游戏模式。以下查询为我做了这个。但是,它很慢。我为存活1分钟的数据做了一个缓存。

此外,users_games_modes ugm加入了user_id而非game_id,就像我希望的那样。我不知道如何在game_id之前将其与games_modes匹配,而无需在加入前移动ugm。如果我之前移动联接,我将如何加入ou1.game_id联接的结果数据? (我希望这是有道理的)

  • 使用ou1.stop
  • 解决此问题

我在where或join语句中的每个项目上都有索引 SELECT ou1.id as oid, ou1.user_id, ou1.game_id as game_id, CONCAT(SUBSTRING(ou1.comment, 1, 7), '...') as comment, users_systems.mic, users_gamernames.user_name, games.game_name, ou1.start, ou1.stop, ou1.system_id as system_id, (select value from users_settings where users_settings.user_id = ou1.user_id and users_settings.setting = 'display_name') as display_name, CASE WHEN ou1.system_id = '1' THEN 'xbox_tile' WHEN ou1.system_id = '2' THEN 'ps3_tile' WHEN ou1.system_id = '3' THEN 'steam_tile' END AS platform, (select value from users_settings where users_settings.user_id = ou1.user_id and users_settings.setting = platform) as platform_tile, GROUP_CONCAT(DISTINCT gm.short_name ORDER BY gm.short_name SEPARATOR ', ') as modes FROM online_users as ou1 LEFT JOIN online_users ou2 ON (ou1.user_id = ou2.user_id and ou1.id < ou2.id and ou1.stop < '2013-01-28 23:59:59') LEFT JOIN users_gamernames ON (users_gamernames.user_id = ou1.user_id AND users_gamernames.system_id = ou1.system_id) LEFT JOIN users_systems ON (ou1.user_id = users_systems.user_id AND ou1.system_id = users_systems.system_id) LEFT JOIN users_games_modes ugm ON (ou1.user_id = ugm.user_id AND ugm.game_id = ou1.game_id) LEFT JOIN games_modes gm ON (ugm.mode_id = gm.id AND ou1.game_id = ou1.game_id) RIGHT JOIN games ON (ou1.game_id = games.id) WHERE ou2.id IS NULL AND ou1.id IS NOT NULL AND ou1.stop<='2013-01-28 23:59:59' GROUP BY ou1.system_id, ou1.user_id ORDER BY ou1.stop ASC LIMIT 50; 是通过PDO动态添加的 语言使用PHP和MySQL

users_games_modes

这是sql-adminer的EXPLAIN输出:

http://i.imgur.com/N1ykp.png

http://i.imgur.com/N1ykp.png

games_modes index:

http://i.imgur.com/m9DLF.png

http://i.imgur.com/m9DLF.png

在线用户指数:

http://i.imgur.com/jf0wz.png

http://i.imgur.com/jf0wz.png

users_games_modes index:

http://i.imgur.com/I0PUR.png

http://i.imgur.com/I0PUR.png

  • 编辑1:删除了2个JOIN,添加了一个CASE,以及一个从运行时删除了一点的子选择,使其在未来的更新中更好一些。
    • 绝大部分的运行时间似乎来自user_id加入。当我删除它,它从16秒到0.32秒。我有users_games_modes的索引。 (我附上了game_id
    • 索引的屏幕截图
  • 编辑2:向users_games_modes添加了users_games_modes列,将运行时间从16秒降低到2.4秒。
    • 更新了{{1}} 4
    • 的索引屏幕截图

1 个答案:

答案 0 :(得分:0)

        SELECT 
            ou1.id as oid,
            ou1.user_id,
            ou1.comment,
            users_systems.mic,
            users_gamernames.user_name,
            games.game_name,
            ou1.start,
            ou1.stop,
            ou1.system_id as system_id,
                (select value from users_settings where users_settings.user_id = ou1.user_id and users_settings.setting = 'display_name') as display_name,
                CASE
                    WHEN ou1.system_id = '1' THEN 'xbox_tile'
                    WHEN ou1.system_id = '2' THEN 'ps3_tile'
                    WHEN ou1.system_id = '3' THEN 'steam_tile'
                END AS platform,
                (select value from users_settings where users_settings.user_id = ou1.user_id and users_settings.setting = platform) as platform_tile,
                ugmt.modes
        FROM online_users as ou1
        LEFT JOIN users_gamernames ON (users_gamernames.user_id = ou1.user_id AND users_gamernames.system_id = ou1.system_id)
        LEFT JOIN users_systems ON (ou1.user_id = users_systems.user_id AND ou1.system_id = users_systems.system_id)
        LEFT JOIN users_games_modes_temp ugmt ON (ou1.user_id = ugmt.user_id AND ugmt.game_id = ou1.game_id)
        RIGHT JOIN games ON (ou1.game_id = games.id)
        WHERE ou1.expired=0
        AND ou1.start<='2013-01-04 21:47'
        AND ou1.stop>='2013-01-04 21:47'
        GROUP BY ou1.id
        ORDER BY ou1.stop DESC
        LIMIT 50;

我删除了users_games_modesgames_modes上的LEFT JOIN和GROUP_CONCAT,并更改了更新users_games_modes的工具中的代码,以便在更改users_games_modes_temp时更新条目。

这将整体查询从16秒更改为0.002秒。

我认为运行时的巨大变化是由于连接为每一行的查询中的所有用户提取users_games_modes所有游戏。