首页 > 解决方案 > SQLALchemy ORM 查询需要很长时间才能运行 - 子查询的变化非常轻微

问题描述

我有两个使用 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 秒。

关于如何解决这个问题的任何想法?

标签: pythonsqlalchemy

解决方案


在当今量子计算和自动驾驶汽车的世界中,我希望多重连接是一个简单的问题。原来是这样。

我的同事提出了这个答案,它奏效了。我错过了 group_by。子查询上的 group_by 显然显着减少了处理时间。

我所要做的就是将 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()

注意最后的 group_by。像魅力一样工作。运行不到一分钟。


推荐阅读