回答

收藏

存储过程SQL执行计划

技术问答 技术问答 240 人阅读 | 0 人回复 | 2023-09-13

我对执行速度非常慢的存储过程感到困惑。存储过程基本上包括使用传入参数(in_id)并将其放入游标中,如下所示:
' k) S- Z1 c+ I  J7 R) vopen tmp_cursor for select col1,col2,col3from table1 tabwhere ((in_id is null) or (tab.id = in_id));  -- tab.id is the PK当我得到具有预定义值的时候SQL在执行查询计划时,使用索引可以获得良好的查询结果。然而,当我从应用程序中调用这个过程时,我看到使用中没有索引,表格被完全扫描,从而降低了性能。
# j5 I6 c1 U2 w. P9 ~如果删除WHERE第一部分(in_id为null)应用程序的性能将再次提高。; E9 u( Y2 W; f% H7 }
为什么在我的应用程序调用过程中不使用索引(传入了in_id)?8 D; j# G# U) B6 V$ B
                                                               
+ m3 c( S) l* R7 y, Y& H    解决方案:                                                                1 G6 U! v5 x" p0 ^" d
                                                                假设这in_id是一个查询参数-不是列名:
9 n1 n2 [& M. m, w7 }- h无论输入什么,查询都必须只有一个执行计划。因此,如果将参数传递给 in_id为NULL,应返回所有行。如果非传输NULL
0 p% u: S) h4 A- M& G+ G# Bin_id,只要返回单个PK值。
+ C$ _( Z# p; K4 `因此,Oracle选择了“最糟糕的”执行程序。计划应对“最坏的情况”。“通用”查询是通向地狱的道路。只需将查询分为两个即可。
& j' W! ]$ e1 [select col1,col2,col3from table1 tabwhere in_id is null or in_id is not null;全表扫描是获取所有行的最佳方法。9 P  U" n& _- g/ i" a
select col1,col2,col3from table1 tabwhere tab.id = in_id;  -- tab.id is the PK这将使用UNIQUE索引扫描是获得单个索引行的最佳方法。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则