Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/60.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 SQL嵌套集查询,使用“in”slow进行连接和子查询_Mysql_Sql_Nested Sets_Nested Set Model - Fatal编程技术网

Mysql SQL嵌套集查询,使用“in”slow进行连接和子查询

Mysql SQL嵌套集查询,使用“in”slow进行连接和子查询,mysql,sql,nested-sets,nested-set-model,Mysql,Sql,Nested Sets,Nested Set Model,我在查询嵌套集结构时遇到了一些问题,该结构的速度很慢~4秒 select node.ID, node.Lft, node.Rgt, node.Level, count(ag.ArticleID) as count from Webshop.Category node left join Webshop.Category parent on parent.Lft between node.Lft and node.Rgt left join Webshop.ArticleGroup ag on p

我在查询嵌套集结构时遇到了一些问题,该结构的速度很慢~4秒

select node.ID, node.Lft, node.Rgt, node.Level, count(ag.ArticleID) as count
from Webshop.Category node
left join Webshop.Category parent on parent.Lft between node.Lft and node.Rgt
left join Webshop.ArticleGroup ag on parent.GroupID = ag.GroupID
    and ag.ArticleID in (
        select a.ID
        from Webshop.Article a
        join Webshop.ArticleOwner ao on ao.ArticleID = a.ID and ao.OWNRID = 1
        join Webshop.ArticleAssortment aa on aa.ArticleID = a.ID and aa.AssortmentID = 6
    )
group by node.ID
having count > 0
explain返回以下内容:

id,select_type,table,type,possible_keys,key,key_len,ref,rows,Extra
1,PRIMARY,node,ALL,NULL,NULL,NULL,NULL,2538,"Using temporary; Using filesort"
1,PRIMARY,parent,ALL,Lft,NULL,NULL,NULL,2538,
1,PRIMARY,ag,ref,fk_ArticleGroup_Group1_idx,fk_ArticleGroup_Group1_idx,4,Webshop.parent.GroupID,9,"Using index"
2,"DEPENDENT SUBQUERY",a,eq_ref,PRIMARY,PRIMARY,4,func,1,"Using index"
2,"DEPENDENT     SUBQUERY",ao,eq_ref,"ArticleIDOWNRID,fk_ArticleOwner_Article1_idx,fk_ArticleOwner_OWNR1_idx",ArticleI    DOWNRID,8,"Webshop.a.ID,const",1,"Using index"
2,"DEPENDENT SUBQUERY",aa,eq_ref,"PRIMARY,fk_ArticleAssortment_Article1_idx",PRIMARY,8,"Webshop.a.ID,const",1,"Using index"
我认为in的子查询使查询速度变慢。有更好的方法吗

谢谢

编辑:

我忘了在子查询中从联接中删除左侧。

您可以尝试联接:


首先,这里有大量的左连接,左连接速度很慢-我假设您使用它们是因为它们在这里是必需的,即连接的表可能不包含匹配项,并且您希望返回Webshop.Category的每一行,而不管是否存在连接的行。 如果不需要左连接,我将转换为内部连接。 如果需要左连接,我会考虑更好的数据库设计,以消除对这些左连接的需要。这可能是不可避免的,但我会感到惊讶

如果无法转换为内部联接,或者查询仍然很慢,则可以尝试先将子查询作为insert into语句运行,创建一个临时表,然后使用该临时表代替子查询(可能是作为联接而不是in语句)

如果这仍然很慢,您可以尝试在ID上为临时表编制索引


在上述所有情况下,我假设表都被合理地索引了?

您的In子查询包含不影响结果的左JOIN子句,因此首先您可以将其更改为:

select node.ID, node.Lft, node.Rgt, node.Level, count(ag.ArticleID) as count
from Webshop.Category node
left join Webshop.Category parent on parent.Lft between node.Lft and node.Rgt
left join Webshop.ArticleGroup ag on parent.GroupID = ag.GroupID
    and ag.ArticleID in (
        select a.ID
        from Webshop.Article a
    )
group by node.ID
having count > 0
现在,一旦我们完成了这项工作,我们可以看到您正在检查aricleid外键的一致性。因此有两种选择。首先,有一个外键,您不必担心这一点,完全删除:

select node.ID, node.Lft, node.Rgt, node.Level, count(ag.ArticleID) as count
from Webshop.Category node
left join Webshop.Category parent on parent.Lft between node.Lft and node.Rgt
left join Webshop.ArticleGroup ag on parent.GroupID = ag.GroupID
group by node.ID
having count > 0
第二种选择,您没有外键。创建一个也不是一个坏主意

更新: 我刚刚注意到在查询的末尾有count>0,这意味着可以用具有相同结果的内部连接替换所有左连接子句

在子查询中将左连接替换为内部连接时,唯一可能改变速度的是将in替换为EXISTS:


根据您的更新更新了我的答案
select node.ID, node.Lft, node.Rgt, node.Level, count(ag.ArticleID) as count
from Webshop.Category node
left join Webshop.Category parent on parent.Lft between node.Lft and node.Rgt
left join Webshop.ArticleGroup ag on parent.GroupID = ag.GroupID
group by node.ID
having count > 0
select node.ID, node.Lft, node.Rgt, node.Level, count(ag.ArticleID) as count
from Webshop.Category node
inner join Webshop.Category parent on parent.Lft between node.Lft and node.Rgt
inner join Webshop.ArticleGroup ag on parent.GroupID = ag.GroupID
WHERE EXISTS (
    SELECT * FROM
        from Webshop.Article a
        join Webshop.ArticleOwner ao on ao.ArticleID = a.ID and ao.OWNRID = 1
        join Webshop.ArticleAssortment aa on aa.ArticleID = a.ID and aa.AssortmentID = 6 
    WHERE a.ID = ag.ArticleID
    )
group by node.ID
-- you don't need HAVING clause here