繁体   English   中英

如何使此SQL查询更高效?

[英]How to Make This SQL Query More Efficient?

我不确定如何使以下SQL查询更有效。 目前,在相当快的服务器上,查询要花费8到12秒的时间,但是对于用户尝试在其上加载带有此代码的页面的网站来说,查询还不够快。 它正在浏览具有许多行的表,例如“ Post”表具有717,873行。 基本上,查询会列出与用户关注的内容相关的所有帖子(最新到最旧)。

是否可以通过仅基于PostTimeOrder获得最后20条结果来使其更快?

我们将不胜感激,或者对可以改善这种情况的任何见解提供任何帮助。 谢谢。

这是完整的SQL查询(很多嵌套):

SELECT DISTINCT p.Id, UNIX_TIMESTAMP(p.PostCreationTime) AS PostCreationTime, p.Content AS Content, p.Bu AS Bu, p.Se AS Se, UNIX_TIMESTAMP(p.PostCreationTime) AS PostTimeOrder
                FROM Post p 
                WHERE (p.Id IN (SELECT pc.PostId
                                FROM PostCreator pc
                                WHERE (pc.UserId IN (SELECT uf.FollowedId
                                                    FROM UserFollowing uf
                                                    WHERE uf.FollowingId = '100')
                                                    OR pc.UserId = '100')
                                ))
                OR (p.Id IN (SELECT pum.PostId
                            FROM PostUserMentions pum
                            WHERE (pum.UserId IN (SELECT uf.FollowedId
                                                    FROM UserFollowing uf
                                                    WHERE uf.FollowingId = '100')
                                                    OR pum.UserId = '100')
                            ))  
                OR (p.Id IN (SELECT ssp.PostId
                                FROM SStreamPost ssp
                                WHERE (ssp.SStreamId IN (SELECT ssf.SStreamId
                                                    FROM SStreamFollowing ssf
                                                    WHERE ssf.UserId = '100'))
                                ))
                OR (p.Id IN (SELECT psm.PostId
                                FROM PostSMentions psm
                                WHERE (psm.StockId IN (SELECT sf.StockId
                                                    FROM StockFollowing sf
                                                    WHERE sf.UserId = '100' ))
                                ))



            UNION ALL
            SELECT DISTINCT p.Id AS Id, UNIX_TIMESTAMP(p.PostCreationTime) AS PostCreationTime, p.Content AS Content, p.Bu AS Bu, p.Se AS Se, UNIX_TIMESTAMP(upe.PostEchoTime) AS PostTimeOrder                 
                FROM Post p
                INNER JOIN UserPostE upe 
                    on p.Id = upe.PostId 
                INNER JOIN UserFollowing uf 
                    on (upe.UserId = uf.FollowedId AND (uf.FollowingId = '100' OR upe.UserId = '100'))  
            ORDER BY PostTimeOrder DESC;    

p.ID in (...)谓词中的p.ID in (...)更改为具有相关子查询的存在谓词可能会有所帮助。 同样由于联合的两半所有查询都从Post表中拉出并可能返回几乎相同的记录,因此您可以通过左外部连接到UserPostE并添加upe.PostID将两者合并为一个查询upe.PostID不为null作为OR条件在WHERE子句中。 UserFollowing仍将内部UserFollowing到UPE。 如果你想在同一职位只记录一次两次upe.PostEchoTime有一次p.PostCreationTime作为PostTimeOrder你需要保持UNION ALL

SELECT 
       DISTINCT -- <<=- May not be needed
       p.Id
     , UNIX_TIMESTAMP(p.PostCreationTime) AS PostCreationTime
     , p.Content AS Content
     , p.Bu AS Bu
     , p.Se AS Se
     , UNIX_TIMESTAMP(coalesce( upe.PostEchoTime
                              , p.PostCreationTime)) AS PostTimeOrder
  FROM Post p 
  LEFT JOIN UserPostE upe 
       INNER JOIN UserFollowing uf 
          on (upe.UserId = uf.FollowedId AND
             (uf.FollowingId = '100' OR
              upe.UserId = '100'))
    on p.Id = upe.PostId 
 WHERE upe.PostID is not null
    or exists (SELECT 1
                 FROM PostCreator pc
                WHERE pc.PostId = p.ID
                  and pc.UserId = '100'
                   or exists (SELECT 1
                                FROM UserFollowing uf
                               WHERE uf.FollowedId = pc.UserID
                                 and uf.FollowingId = '100')
              )
    OR exists (SELECT 1
                 FROM PostUserMentions pum
                WHERE pum.PostId = p.ID
                  and pum.UserId = '100'
                   or exists (SELECT 1
                                FROM UserFollowing uf
                               WHERE uf.FollowedId = pum.UserId
                                 and uf.FollowingId = '100')
              )
    OR exists (SELECT 1
                 FROM SStreamPost ssp
                WHERE ssp.PostId = p.ID
                  and exists (SELECT 1
                                FROM SStreamFollowing ssf
                               WHERE ssf.SStreamId = ssp.SStreamId
                                 and ssf.UserId = '100')
              )
    OR exists (SELECT 1
                 FROM PostSMentions psm
                WHERE psm.PostId = p.ID
                  and exists (SELECT 
                                FROM StockFollowing sf
                               WHERE sf.StockId = psm.StockId
                                 and sf.UserId = '100' )
              )
 ORDER BY PostTimeOrder DESC

可以替换from部分,使其也使用存在子句和相关子查询:

  FROM Post p 
  LEFT JOIN UserPostE upe 
    on p.Id = upe.PostId 
   and ( upe.UserId = '100'
      or exists (select 1
                   from UserFollowing uf
                  where uf.FollwedID = upe.UserID
                    and uf.FollowingId = '100'))

IN示例:

SELECT  ssp.PostId
    FROM  SStreamPost ssp
    WHERE  (ssp.SStreamId IN (
                SELECT  ssf.SStreamId
                    FROM  SStreamFollowing ssf
                    WHERE  ssf.UserId = '100' ))

->

SELECT  ssp.PostId
    FROM  SStreamPost ssp
    JOIN  SStreamFollowing ssf  ON ssp.SStreamId = ssf.SStreamId
    WHERE  ssf.UserId = '100'

所有INs WHERE变得像

JOIN ( ( SELECT pc.PostId AS id ... )
 UNION ( SELECT pum.PostId ... )
 UNION ( SELECT ssp.PostId ... )
 UNION ( SELECT psm.PostId ... ) )

从这些建议中获取您可以做的事情,然后在仍然需要时返回以获取更多建议。 并随身携带SHOW CREATE TABLE

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM