1

ネストされたセット構造のクエリが遅い (~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()サブクエリがクエリを遅くしていると思います。これを行うより良い方法はありますか?

ありがとう。

編集:

leftサブクエリのfrom 結合を削除するのを忘れました。

4

3 に答える 3

0

あなたは試してみることができます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
        join (
        select a.ID as `id`
        from Webshop.Article a
        left join Webshop.ArticleOwner ao on ao.ArticleID = a.ID and ao.OWNRID = 1
        left join Webshop.ArticleAssortment aa on aa.ArticleID = a.ID and aa.AssortmentID = 6
    ) in_ids on ag.ArticleID = in_ids.id
group by node.ID
having count > 0
于 2014-09-09T10:44:24.600 に答える
0

IN サブクエリには、結果に影響を与えない LEFT 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

これが完了すると、AritcleID 外部キーの整合性をチェックしていることがわかります。したがって、2 つのオプションがあります。まず、外部キーがあり、これについて心配する必要はありませんIN。完全に削除します。

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

2 番目のオプションでは、外部キーがありません。作成することは悪い考えではありません。

更新:クエリの最後に あることに気付きました。つまり、すべての句を同じ結果にcount > 0置き換えることができます。left joininner join

left joinsサブクエリでに置き換えたようinner joinに、ここで速度を変更する可能性があるのは、 を に置き換えることだけINですEXISTS

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
于 2014-09-09T10:52:08.193 に答える