python - 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 秒。
关于如何解决这个问题的任何想法?
解决方案
在当今量子计算和自动驾驶汽车的世界中,我希望多重连接是一个简单的问题。原来是这样。
我的同事提出了这个答案,它奏效了。我错过了 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。像魅力一样工作。运行不到一分钟。
推荐阅读
- ios - 线程安全队列
- php - 使用计数器将记录分配给数组
- ubuntu - 如何审核 chrome 扩展的开源代码?
- nginx - 从 NGINX Web 服务器加载 React 静态文件的问题
- javascript - 如何使用相同的参数查询 Graphql 2 对象
- elasticsearch - 我想找到子字符串的确切术语,确切的术语不仅仅是术语的一部分
- javascript - 为什么 javascript 在 Google Chrome 中创建填充?
- javascript - 根据属性分解/组合数组
- java - 无法在回收站视图中显示内部子节点值
- ios - 更新应用程序后,iOS 上的本地文件会发生什么情况?