关于在 Python 里执行 Sql 速度慢的问题,求帮助

2018-05-11 10:30:55 +08:00
 zhangjiabin1010
ps:刚才的主题没编辑完呢,就发出去了。重发一下。
一条多表联合查询 Sql 语句,在 PL/SQL 里执行需要 100 秒,数据有 8 万条。在 Python 里用 CX_Oracle 里执行这条语句,需要很久。我都没等完过,最长的一次等了半小时。后来用 Pandas 连接数据库查询,速度同样很慢,后来我缩小了选择范围。数据量大概有 3000 条左右,执行时间对比如下:

PL/SQL 15 秒
Python cx_oracle 4 分钟 20 秒
python pandas 5 分钟

所以请教有过此问题经验的大佬给解答一下,是什么造成的差异。我该如何调整呢 感谢!!!



PS:优化 SQL 语句我估计不太可行,语句是需求那边直接给的。如果要优化也是需求那边的问题。我的主要疑问是:
#补充 SQL 语句如下:
select d.cplyno, NVL(SUM(NVL(d.n_sum, 0)), 0)
from (SELECT NVL(N_GET_PRM, 0) n_sum, a.c_ply_no cplyno
FROM T_FIN_PLYEDR_COLDUE@linkzysyscard.regress.rdbms.dev.us.oracle.com A,
t_ply_base@linkzysyscard.regress.rdbms.dev.us.oracle.com b
WHERE a.c_cha_cde in ('55001247','55020299000760')
and a.c_edr_no is null
and a.c_ply_no = b.c_ply_no
and b.cardno='0650mt'
/* and a.c_prod_no like '0650mt'|| '%'*/
and exists
(SELECT C_DPT_CDE
FROM t_department
WHERE c_dpt_cde = a.c_dpt_cde
and c_company_cde in
(SELECT c_company_cde
FROM t_department
WHERE C_DPTACC_CDE = '55'))
and b.t_udr_date BETWEEN
to_date('2017-11-30 00:00:00', 'YYYY-MM-DD HH24:MI:SS') AND
to_date('2017-12-31 23:59:59', 'YYYY-MM-DD HH24:MI:SS')
and b.c_b2b_udr_mrk <> 'X'
and N_GOT_PRM = 0
and T_CHARGE_TM is null
union all
SELECT NVL(N_GET_PRM, 0) n_sum, a.c_edr_no cplyno
FROM T_FIN_PLYEDR_COLDUE@linkzysyscard.regress.rdbms.dev.us.oracle.com A,
t_edr_base@linkzysyscard.regress.rdbms.dev.us.oracle.com b,
t_ply_base@linkzysyscard.regress.rdbms.dev.us.oracle.com c
WHERE a.c_cha_cde in ('55001247','55020299000760')
and a.c_edr_no is not null
and a.c_edr_no = b.c_edr_no
and b.c_ply_no=c.c_ply_no
/* and a.c_prod_no like '0650mt' || '%'*/
and exists
(SELECT C_DPT_CDE
FROM t_department
WHERE c_dpt_cde = a.c_dpt_cde
and c_company_cde in
(SELECT c_company_cde
FROM t_department
WHERE C_DPTACC_CDE = '55'))
and b.t_udr_date BETWEEN
to_date('2017-11-30 00:00:00', 'YYYY-MM-DD HH24:MI:SS') AND
to_date('2017-12-31 23:59:59', 'YYYY-MM-DD HH24:MI:SS')
and b.c_b2b_udr_mrk <> 'X'
and N_GOT_PRM = 0
and c.cardno='0650mt'
and T_CHARGE_TM is null) d
group by d.cplyno
order by d.cplyno;
6146 次点击
所在节点    Python
23 条回复
est
2018-05-11 10:34:28 +08:00
问题所在,多半是是一次性把数据载入内存的开销。
myyou
2018-05-11 10:38:12 +08:00
查询数据的游标 cursor 不要执行 cursor.fetchall()一次性取出数据,试试 for data in cursor 逐条去取数据,因为 cursor 是一个迭代器
zhangjiabin1010
2018-05-11 10:41:23 +08:00
@est 在 python 里 我测试: 只执行 sql 语句 curs.execute(sql) ,而不获取查询结果 速度同样很慢。请问下,只执行语句,不 fetchall,会占用很多内存吗?
zhangjiabin1010
2018-05-11 10:43:08 +08:00
@myyou 嗯,是的。我并没有 fetchall。只是 curs.execute(sql)。时间差异依然是那么大~
zhangsen1992
2018-05-11 11:05:37 +08:00
优化 sql 或者 strace -p 看卡在哪
hcymk2
2018-05-11 11:10:13 +08:00
有完整的 python 代码么?
zhangjiabin1010
2018-05-11 11:21:16 +08:00
@hcymk2 就是很简单的连数据库流程,
conn = cx_Oracle.connect('xxxxx/xxxxxx@xx.xx.xx:xx/xxx')
curs = conn.cursor()
query_sql ="sql 语句"
curs.execute(query_sql)
#query_data = curs.fetchll()
#print(query_data)
curs.close()
conn.close()
est
2018-05-11 12:02:03 +08:00
@zhangjiabin1010 就是 fetchall 卡住了。
ioth
2018-05-11 12:07:31 +08:00
不能在程序里面,多表联合查询用一个 sql 语句,能出来就奇怪了,要建立数据模型
和 pl/sql 比较速度没有意义
你用哪种语言都是这样结局,除非 foxpro 或者 powerbuilder 这样本身就是数据库为核心的开发系统
可以什么都不管塞进去 sql
zhangjiabin1010
2018-05-11 12:41:11 +08:00
@est 您看下我补发的图片,从反映上看时间 应该还是浪费在了 execute 的执行上
est
2018-05-11 12:57:05 +08:00
@zhangjiabin1010 ok。那就不清楚了。
zhangjiabin1010
2018-05-11 13:01:57 +08:00
@ioth 不能用一个 sql 语句。是不能执行还是速度慢啊!我从测试上来看,数据量少的话,还是能获取执行结果的。再请问 如果不写在一个 sql 里的话。除了拆分 SQL 语句 还有什么好的方案可以实现吗?
aliipay
2018-05-11 13:05:51 +08:00
看了这么长的 sql 语句,表示我不想说任何话
lieh222
2018-05-11 14:29:25 +08:00
抓个包用 wireshark 看看吧,应该可以解析这个协议
bxtx999
2018-05-11 14:42:14 +08:00
1. python connector 的问题

2. 游标(参考二楼)

使用
for row in cur:
替代
cur.fetchall()


参考: https://stackoverflow.com/questions/26783735/python-5x-slower-than-perl-mysql-query
zhangjiabin1010
2018-05-11 14:53:54 +08:00
@bxtx999 和第二条应该没关系,我测试过第二种方案,效果一样。可能是 connector 的原因。但是我用 pandas 直接连接数据库执行语句,效果和用 cx_oracle 一样慢 。所以现在我也不是很清楚瓶颈卡在哪里了。您有什么好的提议吗?
whx20202
2018-05-11 14:59:20 +08:00
你把 SQL 在数据库节点上执行,输出的 9W 行,直接重定向一下文件,看看用多久?
现在你还没能够证明 SQL 本身很快啊
whx20202
2018-05-11 15:00:28 +08:00
@whx20202 #17 原来这是新帖子 搞错了我再看下
zhangjiabin1010
2018-05-11 15:20:53 +08:00
@whx20202 感谢您的回复~刚才已经找到问题所在啦,原因是我错误的打乱了 sql 语句的格式造成的问题。他们给我 sql 语句之后,我用 双引号 "sql 语句" 存放,然后对缩进格式更改过。最后我直接使用 三引号代码块 """sql 语句""" 放 原格式语句 就好啦、
zhangjiabin1010
2018-05-11 15:26:20 +08:00
原因已经找到:我错误的打乱了 sql 语句的格式造成的问题。他们给我 sql 语句之后,我用 双引号 "sql 语句" 存放,然后对缩进格式更改过。最后我直接使用 三引号代码块 """sql 语句""" 放 原格式语句。可能是某些空格
或者缩进单位影响了 sql 的执行效率。
经验 :大段 SQL 语句要小心更改。最好直接使用三引号代码块

结贴追加补图!

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/453985

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX