MySQL加入/加入性能优化

MySQL加入/加入性能优化,mysql,sql,performance,Mysql,Sql,Performance,我有一个MySQL查询: SELECT p.post_id, p.date_created, p.description, p.last_edited, p.link, p.link_description, p.link_image_url, p.link_title, p.total_comments, p.total_votes, p.type_id, p.user_id

我有一个MySQL查询:

SELECT 
    p.post_id,
    p.date_created,
    p.description, 
    p.last_edited, 
    p.link, 
    p.link_description, 
    p.link_image_url, 
    p.link_title, 
    p.total_comments, 
    p.total_votes, 
    p.type_id, 
    p.user_id 
FROM posts p JOIN posts_to_tribes ptt ON p.post_id=ptt.post_id 
WHERE ptt.tribe_id IN (1, 2, 3, 4, 5) 
GROUP BY p.post_id 
ORDER BY p.last_edited DESC, p.total_votes DESC LIMIT 25
在非并发环境中,此查询运行约172ms,但在并发环境中运行1-2秒(在性能测试期间)

解释输出:

发布到表的索引:


有什么方法可以提高性能吗?

当您确实想要在两个表之间应用连接时,您已经应用了一个
JOIN
操作(SQL中的半连接是使用
in
EXISTS
谓词实现的)

由于您使用了错误类型的
JOIN
,因此您再次使用
分组方式
删除了重复记录。这就浪费了很多CPU周期

以下查询将更快:

SELECT 
    p.post_id,
    p.date_created,
    p.description, 
    p.last_edited, 
    p.link, 
    p.link_description, 
    p.link_image_url, 
    p.link_title, 
    p.total_comments, 
    p.total_votes, 
    p.type_id, 
    p.user_id 
FROM posts p 
WHERE p.post_id IN (
  SELECT ptt.post_id
  FROM posts_to_tribes ptt
  WHERE ptt.tribe_id IN (1, 2, 3, 4, 5)
)
ORDER BY p.last_edited DESC, p.total_votes DESC LIMIT 25

你仍然应该在
(p.post\u id)
(ptt.tribe\u id,ptt.post\u id)
上有索引。你需要一个用于
发布到部落的复合索引。
索引(tribe\u id,post\u id)

groupby
是为了补偿
JOIN
的行数爆炸。这里有一个比(选择…)中的
更好的解决方法:


在ptt.tribe\u id上可能有一个索引基本经验法则:在“决策”上下文中使用的任何字段(join,where,order by)都应该有一个索引。感谢您的回答,我在posts\u to\u tribes.tribe\u id上添加了一个索引,但没有任何更改。。查询现在运行约188ms。。可能是我做错了。为什么172ms的执行时间是可以接受的,但是1-2秒的执行时间是不可以接受的?我有REST端点来完成这个功能。。现在,在性能测试期间,它在并发环境中运行~6秒,而其他端点运行~2-3个扇区。现在,此查询也运行~156ms,我将在并发环境中的性能测试中检查它。您是否如我所示,在
ptt
的两列上都放置了索引?在posts\u to\u部落中,我有一个PK(部落id,post\u id). 同样在posts表中,post_id也是PK。我应该在这些字段上添加单独的索引吗?@alexanoid:Aha,好的。不,PK应该足够了。对不起,我的MySQL知识太有限了。我相信这会优化您在Oracle中的查询,不过…非常感谢!这个查询运行140ms,还有一个问题,我们需要关于p.last\u edited和p.total\u投票的索引吗?不。我不相信
索引(last\u edited,total\u voces)
(按顺序组合)会有任何好处。(1) 它将从子查询开始,子查询不允许它访问该索引。(2) 这些列听起来像是要更改很多的列,因此在
UPDATE
中会增加开销。你会被一个“文件排序”卡住。我缺少什么?此查询将返回重复的行…?Oops--将
DISTINCT
添加到我的子查询中。
SELECT  p.post_id, p.date_created, p.description, p.last_edited,
        p.link, p.link_description, p.link_image_url, p.link_title,
        p.total_comments, p.total_votes, p.type_id, p.user_id
    FROM  posts p
    JOIN  
      ( SELECT  DISTINCT  post_id
            FROM  posts_to_tribes
            WHERE  tribe_id IN (1, 2, 3, 4, 5)
      ) AS ptt USING (post_id)
    ORDER BY  p.last_edited DESC,
              p.total_votes DESC
    LIMIT  25