关于Python中执行SQL速度慢的问题,求帮助
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,
[email protected] 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,
[email protected] b,
[email protected] 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;
关于Python中执行SQL速度慢的问题,求帮助
问题所在,多半是是一次性把数据载入内存的开销。
我无法理解你的问题
查询数据的游标 cursor 不要执行 cursor.fetchall()一次性取出数据,试试 for data in cursor 逐条去取数据,因为 cursor 是一个迭代器
在 python 里 我测试: 只执行 sql 语句 curs.execute(sql) ,而不获取查询结果 速度同样很慢。请问下,只执行语句,不 fetchall,会占用很多内存吗?
嗯,是的。我并没有 fetchall。只是 curs.execute(sql)。时间差异依然是那么大~
优化 sql 或者 strace -p 看卡在哪
有完整的 python 代码么?
就是很简单的连数据库流程,
conn = cx_Oracle.connect(‘xxxxx/[email protected]:xx/xxx’)
curs = conn.cursor()
query_sql ="sql 语句"
curs.execute(query_sql)
#query_data = curs.fetchll()
#print(query_data)
curs.close()
conn.close()
就是 fetchall 卡住了。
不能在程序里面,多表联合查询用一个 sql 语句,能出来就奇怪了,要建立数据模型
和 pl/sql 比较速度没有意义
你用哪种语言都是这样结局,除非 foxpro 或者 powerbuilder 这样本身就是数据库为核心的开发系统
可以什么都不管塞进去 sql
您看下我补发的图片,从反映上看时间 应该还是浪费在了 execute 的执行上
ok。那就不清楚了。
不能用一个 sql 语句。是不能执行还是速度慢啊!我从测试上来看,数据量少的话,还是能获取执行结果的。再请问 如果不写在一个 sql 里的话。除了拆分 SQL 语句 还有什么好的方案可以实现吗?
看了这么长的 sql 语句,表示我不想说任何话
抓个包用 wireshark 看看吧,应该可以解析这个协议
- python connector 的问题
2. 游标(参考二楼)
使用
for row in cur:
替代
cur.fetchall()
参考: https://stackoverflow.com/questions/26783735/python-5x-slower-than-perl-mysql-query
和第二条应该没关系,我测试过第二种方案,效果一样。可能是 connector 的原因。但是我用 pandas 直接连接数据库执行语句,效果和用 cx_oracle 一样慢 。所以现在我也不是很清楚瓶颈卡在哪里了。您有什么好的提议吗?
感谢您的回复~刚才已经找到问题所在啦,原因是我错误的打乱了 sql 语句的格式造成的问题。他们给我 sql 语句之后,我用 双引号 “sql 语句” 存放,然后对缩进格式更改过。最后我直接使用 三引号代码块 “”“sql 语句”"" 放 原格式语句 就好啦、
原因已经找到:我错误的打乱了 sql 语句的格式造成的问题。他们给我 sql 语句之后,我用 双引号 “sql 语句” 存放,然后对缩进格式更改过。最后我直接使用 三引号代码块 “”“sql 语句”"" 放 原格式语句。可能是某些空格
或者缩进单位影响了 sql 的执行效率。
经验 :大段 SQL 语句要小心更改。最好直接使用三引号代码块
结贴追加补图!
如果是 buffer cursor 的话,那么 execute 阶段就已经完成数据加载到内存解析完成了吧
而且事实上 cx_oracle 是用 c 写的啊,和 python 语言性能并未有直接关系
试过 pymysql 纯 python 写的从 mysql 取出百万条数据也不是很慢的吧
改 sql 要小心,确实。

