oracle – 如何在PL / SQL中内联变量?
情况
对于Oracle 11.2.0.2.0中大量数据的中型查询,我的查询执行计划有些麻烦.为了加快速度,我引入了一个大致如下的范围过滤器: PROCEDURE DO_STUFF( org_from VARCHAR2 := NULL,org_to VARCHAR2 := NULL) -- [...] JOIN organisations org ON (cust.org_id = org.id AND ((org_from IS NULL) OR (org_from <= org.no)) AND ((org_to IS NULL) OR (org_to >= org.no))) -- [...] 如您所见,我想限制使用可选范围的组织编号的组织的联合.客户端代码可以调用(假定为快)或不(非常慢)限制的DO_STUFF. 麻烦 麻烦的是,PL / SQL将为上述org_from和org_to参数创建绑定变量,这在大多数情况下将是我期望的: -- [...] JOIN organisations org ON (cust.org_id = org.id AND ((:B1 IS NULL) OR (:B1 <= org.no)) AND ((:B2 IS NULL) OR (:B2 >= org.no))) -- [...] 解决方法 只有在这种情况下,当我只是内联值时,我测量出查询执行计划好多了,即当Oracle执行的查询实际上是这样的 -- [...] JOIN organisations org ON (cust.org_id = org.id AND ((10 IS NULL) OR (10 <= org.no)) AND ((20 IS NULL) OR (20 >= org.no))) -- [...] “很多”,我的意思是快5-10倍.请注意,查询执行非常少,即每月一次.所以我不需要缓存执行计划. 我的问题 >如何在PL / SQL中进行内联值?我知道大约EXECUTE IMMEDIATE,但我更喜欢PL / SQL编译我的查询,而不是做字符串连接.
有两条路.如果您为参数传递NULL,那么您正在选择所有记录.在这种情况下,全表扫描是检索数据的最有效方法.如果您传递值,则索引读取可能会更有效率,因为您只选择一小部分信息. 当您使用绑定变量制定查询时,优化器必须做出决定:是否应该假设大部分时间将传递值,否则您将通过null?难.所以看另外一种方法:当你只需要选择一个记录子集,或者当你需要选择所有的记录时,做索引读取,做全表扫描效率会更低吗? 看起来优化器已经全面扫描了全面扫描,因为它是覆盖所有可能性的最低效的操作. 而当您硬编码值时,Optimizer立即知道10 IS NULL评估为FALSE,因此它可以权衡使用索引读取的优点,以找到所需的子集记录. 那么该怎么办?正如你所说的,这个查询只能运行一个月一次,我认为只需要对业务流程进行一些小的更改,以便分开查询:一个用于所有组织,一个用于一个子组织.
好的,所以你有一对绑定变量指定一个范围.根据值的分布,不同的范围可能适合不同的执行计划.也就是说,这个范围(可能)适合索引范围扫描… WHERE org.id BETWEEN 10 AND 11 …而这可能更适合于全表扫描… WHERE org.id BETWEEN 10 AND 1199999 那就是“变形偷窥”发挥作用的地方. (当然取决于值的分布). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |