对连接的大表的子查询非常慢

时间:2016-05-10 06:50:40

标签: sql postgresql postgresql-performance

我有以下查询,

SELECT * FROM users, 
(SELECT * 
FROM mastery 
WHERE champion_rank = 1 
ORDER BY global_rank ASC 
LIMIT 3) as ranks
WHERE users.id = ranks.user_id

掌握有22M行,用户有5M行。上面的查询需要1800毫秒才能完成。

问题是以下子查询在运行时需要2.5ms才能执行

SELECT * 
FROM mastery 
WHERE champion_rank = 1 
ORDER BY global_rank ASC 
LIMIT 3

从users表中检索单个用户需要2.5ms

SELECT * FROM users WHERE id = 4234523

理论上如果我只是修改了我的代码来执行第一个子查询,然后对于返回的每一行运行一个额外的查询,整个过程将花费2.5 +(3 * 2.5)= 10 ms来运行。

当然postgres做了一些奇怪的事情?

可以找到数据库的结构和索引here

2 个答案:

答案 0 :(得分:0)

您的查询运行缓慢,因为它必须为用户的5M行中的每一行运行已排序的子查询。

你可以更好地进行连接单次传递,并使用rank()窗口函数来过滤你想要的3个顶级传递:

SELECT users.*, (ranks.mastery).*
FROM (
  SELECT mastery, rank() OVER (ORDER BY global_rank)
  FROM mastery
  WHERE champion_rank = 1
  ) as ranks
JOIN users ON (users.id = ranks.user_id)
WHERE ranks.rank <= 3;

答案 1 :(得分:0)

确定问题,我加入的两个字段的数据类型不同。 Mastery的用户ID是数据类型numeric,Users id是数据类型integer,它必须将每一行都转换为新类型。

因此查询时间长。