假设,我们有两个实体\表 - 用户和游戏(可以是任何东西)。用户可以将多个游戏标记为收藏夹。所以我们还有一个user_favourite_game(user_id,game_id)表。
然后假设,用户正在获取所有可用游戏的列表,其中一些应该具有"收藏夹"标志 = true(使用分页,因此我们假设每次获取 20 个游戏)。所以我在这里看到两种方法:
- 我们可以发出一个请求来填充"收藏夹"字段,例如
SELECT
g.*,
ufg.game_id IS NOT NULL AS favourite
FROM
games g LEFT JOIN
user_favourite_game ufg ON ufg.user_id = :userId AND g.id = ufg.game_id
ORDER BY
g.id;
- 我们可以选择游戏,然后执行 20 个请求来检查游戏是否是用户最喜欢的游戏。
哪种方法更好,为什么?还有其他想法吗?
在上一个项目中,我们使用了第二种方法,因为每个实体所需的计算都很复杂。因此,它比上面的示例中要复杂得多,并且几乎不可能在单个查询中计算。
但总的来说,在我看来,在这种简单的情况下,使用 JOIN 的单个查询应该比 20 个简单查询运行得更快。虽然,我不确定当我们user_favourite_game表中有大量数据时它会如何表现
将数据库用于其设计目的,并让它将结果作为原始查询的一部分提供。
数据库在用户收藏的游戏桌上执行外部联接所花费的时间可能少于对收藏夹标志的 20 个单独请求的网络开销。
确保表在增长时适当地编制索引,并具有准确的统计信息。
这不是一个硬性规定,实际的性能测试应该指导,但我观察到许多应用程序受到网络干扰的损害。如果每个请求的往返费用为 250 毫秒,则 20 个呼叫将非常昂贵。如果您的往返费用是 1 毫秒,人们可能永远不会注意到。
触发 20 个查询(无论它们有多简单)总是会减慢应用程序的速度。因素包括网络成本、查询运行等。
您应该触发一个查询以获取可用游戏的页面,然后进行另一个查询,通过传递该页面中存在的游戏 ID 来获取该用户的"收藏夹"游戏列表。然后通过循环结果来设置/取消设置标志。这样,您只需进行 2 次数据库调用,它将显着提高性能。