问题描述
这是我的查询的样子:
SELECT disTINCT user.id AS user_id,messaged_date
FROM users
JOIN (
SELECT MIN(message_date) AS messaged_date,user_id
FROM messages
GROUP BY user_id
) messages_join ON user.id = messages_join.user_id
WHERE (user.client_id IN ('1234')
AND user.status IN ('statusA')
);
-
messages
表具有两个列->user_id
和messaged_date
。我既有索引,也有多列索引(user_id,messaged_data asc nulls last)
-
messages
表很大。大小约为50Gb。 - 该查询要花费年龄(5分钟以上)才能运行。
- 如果删除该联接,它将在1秒内返回。
- 我想每
user_id
排一行
如何使查询执行更快?显然,在min
加上group_by
上的联接是原因。 (EXPLAIN
确认了这一点。)
我尝试了loose index scan,aka a "skip scan",它本身表现不错,但是加入结果时却无济于事。
解决方法
这是问题的原始版本。
子查询非常奇怪。看来您只想exists
:
SELECT u.id AS user_id
FROM users u
WHERE u.client_id IN ('1234') AND
u.status IN ('statusA') AND
EXISTS (SELECT 1
FROM messages m
WHERE m.user_id = u.id
);
这可以利用messages(user_id)
上的索引。
也许您想要这样:
SELECT DISTINCT ON (users.id)
users.id AS user_id,messages.message_date AS messaged
FROM users
JOIN messages
ON users.id = messages.user_id
WHERE users.client_id = '1234'
AND users.status = 'statusA'
ORDER BY users.id,message.message_date;
可以加快查询速度的索引:
CREATE INDEX ON users (client_id,status);
CREATE INDEX ON messages (user_id);