Python SQLALchemy ORM查询需要很长时间才能运行-子查询中的更改非常轻微

Python SQLALchemy ORM查询需要很长时间才能运行-子查询中的更改非常轻微,python,sqlalchemy,Python,Sqlalchemy,我有两个使用SQLAlchemy ORM的子查询版本: subq1 = session.query(su.DistCode,dr.RtrId, su.RtrCode, su.InvoiceNo, su.SlabId, sh.SchId, sslab.PurQty, sslab.DiscPer, sslab.FlatAmt).\ join(sh).\ join(dr, and_(dr.DistCode==su.DistCode, dr.RtrCode==su.RtrCode)).\

我有两个使用SQLAlchemy ORM的子查询版本:

subq1 = session.query(su.DistCode,dr.RtrId, su.RtrCode, su.InvoiceNo, su.SlabId, sh.SchId, sslab.PurQty, sslab.DiscPer, sslab.FlatAmt).\
    join(sh).\
    join(dr, and_(dr.DistCode==su.DistCode, dr.RtrCode==su.RtrCode)).\
    join(sslab,and_(su.SlabId==sslab.SlabId, sh.SchId==sslab.SchId)).\
    subquery()
另一个是:

subq1 = session.query(su.DistCode,dr.RtrId, su.RtrCode, su.InvoiceNo, su.SlabId, sh.SchId).\
    join(sh).\
    join(dr, and_(dr.DistCode==su.DistCode, dr.RtrCode==su.RtrCode)).\
    subquery()
两者之间的唯一区别是包含具有以下内容的联接:

.join(sslab,and_(su.SlabId==sslab.SlabId, sh.SchId==sslab.SchId))
我使用这两个版本的代码,一个接一个

subq2 = session.query(ds.DistCode, ds.RtrId, ds.PrdCde, ds.SalInvDte, ds.SalInvNo,
                     (ds.SalInvQty*ds.SelRateBeforTax).label('SBT'), ds.SalInvSch, 
                     pdet.ProductId, dr.RtrChannelCode, dr.GeoName, dr.RtrClassCode, dr.RtrCode,
                     dr.RtrGroupCode).join(pdet).outerjoin(dr, and_(ds.DistCode==dr.DistCode, ds.RtrId==dr.RtrId)).subquery()

rset = session.query(subq2.c.DistCode, subq2.c.RtrId, subq2.c.RtrCode, subq2.c.SalInvNo,
                     subq2.c.SalInvDte, subq2.c.PrdCde, subq2.c.ProductId, subq2.c.SBT, subq2.c.SalInvSch,
                     subq2.c.RtrChannelCode, subq2.c.RtrClassCode, subq2.c.RtrGroupCode,
                     subq2.c.GeoName, subq1.c.SlabId, subq1.c.SchId).join(subq1,and_(subq1.c.DistCode==subq2.c.DistCode, subq1.c.RtrId==subq2.c.RtrId, subq1.c.InvoiceNo==subq2.c.SalInvNo)).join(spid,and_(subq2.c.ProductId==spid.ProductID, subq1.c.SchId==spid.SchemeID))

df = pd.read_sql(rset.statement, rset.session.bind)
结果让我目瞪口呆。第一个查询进入无限循环(或需要10小时以上的时间;而另一个查询则需要26秒的时间!)

作为解决此问题的一种调试方法,我以独立查询的方式运行了两个版本的“subq1”,两个版本都运行得非常好,运行时间不到3秒


有没有关于如何深入了解这个问题的想法?

在当今量子计算和自动驾驶汽车的世界中,我认为多重连接是一个简单的问题。事实证明确实如此

我的同事提出了这个答案,它奏效了。我错过了group_by。group_by on子查询显然大大缩短了处理时间

我所要做的就是将subq1更改为:

 subq1 = session.query(su.DistCode,dr.RtrId, su.RtrCode, su.InvoiceNo, su.SlabId, 
                          sh.SchId, sslab.PurQty.label('PQ'), 
                      sslab.DiscPer.label('DP'), 
                      sslab.FlatAmt.label('FA')).join(sh).join(dr, and_(dr.DistCode==su.DistCode, dr.RtrCode==su.RtrCode)).join(sslab,and_(su.SlabId==sslab.SlabId, sh.SchId==sslab.SchId)).group_by(su.DistCode,dr.RtrId, su.RtrCode, su.InvoiceNo, su.SlabId, sh.SchId, sslab.DiscPer, sslab.FlatAmt, sslab.PurQty).subquery()

<强>最后注意GROPYBY。工作很有魅力。在不到一分钟的时间内运行。< /强>

您考虑添加另一个连接“轻度更改”。?使用
EXPLAIN
或您的DBMS的等效工具来检查查询计划和估计。SQL很少会产生无限循环,除非使用递归CTE,但错误的联接可能会导致要处理的行数非常多。纯粹的推测,因为您没有提供数据样本,但您的联接可能会在这种情况下产生重复的行挂载进一步的连接将永远持续下去,分组将消除重复。仅使用
DISTINCT
将产生相同的效果。此外,多个连接绝不是一个简单的问题。在n表连接中有n!种连接方式。除此之外,还有应用谓词的所有不同方式,以及可能的查询计划数长得太快了。