有两个表:posts
(约5,000,000行)和relations
(约8,000行)。
posts
列:
-------------------------------------------------
| id | source_id | content | date (int) |
-------------------------------------------------
relations
列:
---------------------------
| source_id | user_id |
---------------------------
我为从posts
获取10个与特定用户相关的最近行编写了一个MySQL查询:
SELECT p.id, p.content
FROM posts AS p
LEFT JOIN relations AS r
ON r.source_id = p.source_id
WHERE r.user_id = 1
ORDER BY p.date DESC
LIMIT 10
然而,执行它需要约30秒。
relations
,(source_id, user_id)
以及(user_id)
,(source_id)
,(date)
(date, source_id)
处的posts
已有索引
EXPLAIN
结果:
如何优化查询?
答案 0 :(得分:1)
你可以在posts表的日期列上放一个索引,我相信这有助于订单的速度。
您还可以在使用其他where语句进行排序之前尝试减少结果数量。例如,如果你知道今天可能有10条记录带有正确的user_id,你可以将日期限制在今天(或者根据你的实际数据将N天限制在后面)。
答案 1 :(得分:1)
您的WHERE子句将外部联接呈现为内部联接(因为在外部联接的伪记录中,user_id将始终为null,从不为1)。
如果你真的希望这是一个外部联接,那么它是完全多余的,因为{{1>}中的每个记录在posts
当然有或没有匹配。您的查询将是
relations
如果您不希望它真的是外部联接,但想要1>} {/ 1}}中的匹配,那么我们在谈论表格中的存在,{{1}因此:或select id, content
from posts
order by "date" desc limit 10;
条款:
relations
EXISTS
上应该有一个索引 - 按此顺序,我们可以先选择IN
1,然后获取所有需要select id, content
from posts
where source_id in
(
select source_id
from relations
where user_id = 1
)
order by "date" desc
limit 10;
的数组,然后我们会查找。
当然,您还需要一个relations(user_id, source_id)
的索引,因为user_id
是一个ID。您甚至可以使用复合索引source_id
来加快速度,因此不必再读取表本身 - 所需的所有信息都已在索引中。
更新:以下是相关的posts(source_id)
查询:
source_id
答案 2 :(得分:0)
试试这个
SELECT p.id, p.content FROM posts AS p
WHERE p.source_id IN (SELECT source_id FROM relations WHERE user_id = 1)
ORDER BY p.date DESC
LIMIT 10
答案 3 :(得分:0)
我会考虑以下几点: -
首先,您只需要与用户相关的帖子中的10个最新行。所以,INNER JOIN
应该做得很好。
SELECT p.id, p.content
FROM posts AS p
JOIN relations AS r
ON r.source_id = p.source_id
WHERE r.user_id = 1
ORDER BY p.date DESC
LIMIT 10
如果要获取没有LEFT JOIN
映射的记录,则需要relations
。因此,执行LEFT JOIN
会导致左表的全表扫描,根据您的信息,包含约5,000,000行。这可能是您查询的根本原因。
要进一步优化,请考虑将WHERE
子句移到ON
子句中。
SELECT p.id, p.content
FROM posts AS p
JOIN relations AS r
ON (r.source_id = p.source_id AND r.user_id = 1)
ORDER BY p.date DESC
LIMIT 10
答案 4 :(得分:0)
我会尝试使用关系的综合索引:
INDEX source_user (user_id,source_id)
并将查询更改为:
SELECT p.id, p.content
FROM posts AS p
INNER JOIN relations AS r
ON ( r.user_id = 1 AND r.source_id = p.source_id )
ORDER BY p.date DESC
LIMIT 10