选择在很多行的桌子上花很多时间

时间:2018-05-13 21:31:36

标签: mysql indexing query-optimization

我有这个选择:

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秒。

enter image description here 有什么改进的想法吗?

`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,

任何提高速度的想法?我也尝试在喜欢数据上添加索引,但没有注意到差异。

2 个答案:

答案 0 :(得分:3)

这是您的查询:

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的开销,但这会加快查询的连接和过滤部分。

答案 1 :(得分:1)

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

警告:如果没有人喜欢你,结果集可能与此查询不同。如果这是一个问题,我会重新制定它以使用“衍生的”#39;表

通过将cadastro查找移动到子查询中,我认为行动发生的频率低于cadastro在JOIN中的情况。这不是通用优化 - 请注意WHERE子句很复杂,因为它涉及多个表。我不清楚p上的索引是否会完全通过data,并且对LIMIT提供帮助。如需进一步调查,请提供EXPLAIN FORMAT=JSON SELECT ...