Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/74.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 2非常快速和简单的查询在合并在一起时速度非常慢_Mysql_Sql_Database_Query Performance_Mysql 5.7 - Fatal编程技术网

Mysql 2非常快速和简单的查询在合并在一起时速度非常慢

Mysql 2非常快速和简单的查询在合并在一起时速度非常慢,mysql,sql,database,query-performance,mysql-5.7,Mysql,Sql,Database,Query Performance,Mysql 5.7,我有这两张桌子。我正在尝试查找id为1的用户已加入的组。 以下是每个表的10行(仅显示其布局): PostTable(57272行,主键id): JoinedGroupsTable(258404行,唯一索引用户ID,groupid): 当我尝试运行此查询时,它几乎在3秒钟内完成,速度非常慢: SELECT * FROM posttable p WHERE groupid in (SELECT groupid FROM joinedgroupstable WHERE userid=1) ORDE

我有这两张桌子。我正在尝试查找id为1的用户已加入的组。 以下是每个表的10行(仅显示其布局):

PostTable(57272行,主键id):

JoinedGroupsTable(258404行,唯一索引用户ID,groupid):

当我尝试运行此查询时,它几乎在3秒钟内完成,速度非常慢:

SELECT * FROM posttable p 
WHERE groupid in (SELECT groupid FROM joinedgroupstable WHERE userid=1)
ORDER BY p.ID DESC LIMIt 25;
我也尝试过使用内部连接而不是WHERE IN,但结果大致相同:

SELECT * FROM posttable p 
INNER JOIN joinedgroupstable jg ON userid=1 AND jg.groupid=p.groupid
ORDER BY p.ID DESC LIMIt 25;
以下是两个查询的解释选择(两个查询的结果相同):

问题是,单独运行每个查询非常快:

SELECT * FROM posttable p ORDER BY p.ID DESC LIMIt 25;

SELECT * FROM joinedgroupstable WHERE userid=1

考虑到每个查询本身运行速度极快,但合并时运行速度较慢,有什么不对?

要加快第一个查询,请添加以下索引:

create index ix1 on joinedgroupstable (userid, groupid);

create index ix2 on PostTable (id);
第二个问题在我看来是错误的。

不同的答案:

create index ix10 on joinedgroupstable (userid);

create index ix11 on posttable (groupid);

select p.* 
  from posttable p
  join joinedgroupstable g on p.groupid = g.groupid
  where g.userid = 1
  order by p.id desc
  limit 25;

如果您的问题被简化,并且您的
PostTable
包含的列比您向我们展示的多,则您的
按顺序。。。LIMIT…
子句导致大量排序浪费

您可以执行所谓的“延迟连接”。首先获取适当的id值,然后使用它们检索行

select p.* 
  from posttable p
  join (
       select a.id
       from posttable a
       join joinedgroupstable g on a.groupid = g.groupid
      where g.userid = 1
      order by a.id desc
      limit 25
     ) sel on sel.id = p.id
order by p.id desc
limit 25;

这就限制了昂贵的
订单。。。限制…
操作仅限于
id
列,然后使用所选的
id
值仅命中主表25次。

我将使用
EXISTS
替代,这也可以更好地执行:

select p.*
from posttable p 
where exists (select 1 
              from joinedgroupstable jg
              where jg.groupid = p.groupid and jg.userid = 1
              )
order by p.id desc
limit 25;

您使用的是什么版本的MySQL?能否包括每个表有多少行?@stickybit 5.7.22-0ubuntu18.04。1@TheImpaler如果我不得不猜测的话,问题出在订单限制上。在运行这些查询之后,它仍然很慢。已经有一个唯一的索引(userid,groupid)并且id是pkposttable@Krestek-如果
(userid,groupid)
是唯一的,则将其作为
主键
,并删除
id
。这可能会提供一个加速,因为PK与数据“聚集”在一起。@RickJames为了排序,我实际上在其他查询中使用了id,尽管我将从表中删除PK,但我不在表中使用它,谢谢!就是这样!我只是再次检查,发现问题是由订单造成的。不过,你的解决方案解决了这个问题,谢谢!奇怪的这在不必删除order by p.id desc的情况下修复了它。因此,加入JoinedGroup是否会导致order by变慢?无论如何,这也有效,所以我也会接受这个答案。谢谢大家!@Krestek我猜这个表单允许MYSQL使用
p.id
上的索引来获取最新的帖子,然后检查它们是否在合适的组中。对于每个候选
p
,最有可能分别执行/评估相关查询,但在这种情况下,这比获取每个相关p,然后为最近的p排序要便宜得多。@uuerdo-Ah,因此基本上它重复了“exists”查询每一个p行,通常不应该是go to,但它在这里工作,因为它选择较少的p行进行排序。明白了,谢谢:>好吧,让我们看看
解释
@Krestek是的,那是我的猜测。
create index ix10 on joinedgroupstable (userid);

create index ix11 on posttable (groupid);

select p.* 
  from posttable p
  join joinedgroupstable g on p.groupid = g.groupid
  where g.userid = 1
  order by p.id desc
  limit 25;
select p.* 
  from posttable p
  join (
       select a.id
       from posttable a
       join joinedgroupstable g on a.groupid = g.groupid
      where g.userid = 1
      order by a.id desc
      limit 25
     ) sel on sel.id = p.id
order by p.id desc
limit 25;
select p.*
from posttable p 
where exists (select 1 
              from joinedgroupstable jg
              where jg.groupid = p.groupid and jg.userid = 1
              )
order by p.id desc
limit 25;