select在有很多行的表上花费了很多时间

h9vpoimq  于 2021-06-21  发布在  Mysql
关注(0)|答案(2)|浏览(353)

我有这个选择:

select 'like' prefix
     , l.post
     , l.data as data
     , l.user
     , concat(k.user, ' liked you') as logs 
  from likes l 

inner join posts p on l.post = p.id 
inner join cadastro k on l.user = k.id 
where p.user = 1 and l.user <> p.user

order by data desc
limit 10

花了2.3993秒。

有什么改进的办法吗?

`likes` (
  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `user` int(11) UNSIGNED NOT NULL,
  `post` int(11) UNSIGNED NOT NULL,
  `data` datetime NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `user_post` (`user`,`post`),
  KEY `post_user` (post, user),
  FOREIGN KEY (`user`) REFERENCES cadastro (`id`),
  FOREIGN KEY (`post`) REFERENCES posts (`id`) ON DELETE CASCADE
)

`posts` (
  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,

`cadastro` (
  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,

有什么办法可以加快速度吗?我还尝试在likes数据上添加索引,但没有发现任何差异。

8aqjt8rx

8aqjt8rx1#

这是您的问题:

select 'like' as prefix, l.post, l.data as data, l.user,
        concat(k.user, ' liked you') as logs
from likes l join
     posts p
     on l.post = p.id oin
     cadastro k
     on l.user = k.id 
where p.user = 1 and l.user <> p.user
order by data desc
limit 10;

对于这个查询,您需要索引 post(user, id) , likes(post, user, data) ,和 cadastro(id, user) .
你不可能做太多的事情来消除系统的开销 order by ,但这会加快查询的连接和筛选部分。

t2a7ltrp

t2a7ltrp2#

select  'like' prefix ,
        l.post ,
        l.data as data ,
        l.user ,
        ( SELECT concat(user, ' liked you')
              FROM cadastro  WHERE id = l.user ) AS logs
    from  likes l
    inner join  posts p  ON l.post = p.id
    where  p.user = 1
      and  l.user <> p.user
    order by  data desc
    limit  10

索引:

p: (user, data, id)  -- 'covering'; helps WHERE; may help ORDER BY
l: (post)
cadastro: I assume you have PRIMARY KEY(id)

进一步改进:更改 likes 索引自

PRIMARY KEY (`id`),
UNIQUE KEY `user_post` (`user`,`post`),
KEY `post_user` (post, user),

PRIMARY KEY(post, user),
INDEX(user, post)

把它扔掉 id .
警告:如果没有人“喜欢你”,那么这个查询的结果集可能不同。如果这是一个问题,我将重新格式化它以使用“派生”表。
通过将cadastro查找移到子查询中,我认为与cadastro位于子查询中相比,该操作的发生频率更低 JOIN . 这不是一个通用的优化——请注意 WHERE 子句很复杂,因为它涉及多个表。我不清楚索引是否 p 会一直坚持下去的 data ,并帮助 LIMIT . 为进一步调查,请提供 EXPLAIN FORMAT=JSON SELECT ...

相关问题