问题描述
我的环境:
让我解释一下这个问题。我通过Azure Kubernetes中的REST服务运行的大型查询遇到一些问题。该查询使用大量表,并且未设置绑定变量时需要花费大量时间。实际上,当通知绑定变量时,查询仅需1.5秒。我试图说服开发查询的团队强制告知参数,但是他们说需求是原样,并且不能受到挑战。
我通过创建一些不存在的索引来最大程度地改善了查询,甚至我运行了sql调整任务来收集更多细节。我甚至尝试根据Tuning Advisor的建议创建一个新的sql配置文件,但是它使查询变得更慢,因此最后我放弃了它。当没有绑定值的查询单独运行时,需要14秒才能完成。但是,当同一查询成为大规模压力测试的一部分(同时有10至15个威胁)时,某些进程会因超时而终止,因此查询达到60秒而没有完成。
我一直看到相同的等待事件:PGA内存操作(在这方面,我还尝试设置更多的PGA,甚至增加了隐藏参数_pga_max_size
和{{1}的默认值}。我也尝试使用手动工作区设置运行它,我禁用了_smm_max_size
,但没有任何一项使查询运行得更快或更慢。
再次澄清一下:当查询没有将设置为特定值的变量绑定时,就会发生此问题。只有在这种情况下,我才会遇到问题。
我的最后一个想法是创建一个物化视图,并在提交时快速刷新。数据库上的DML活动很少,因此数据并发不会成为问题,因此我相信不会有太多的锁定。我读到,自11g以来,Oracle在提交方面的快速刷新已经有了很多改进。但是,我不知道该怎么解决。我应该使用整个查询来创建一个MVIEW还是将其拆分?
在这件事上,我想征求您的意见。或者即使您看到可以优化的内容。不要犹豫,要求任何澄清。我试图将执行计划添加到问题中,但是我达到了最大的字符限制。
非常感谢您的支持。
查询如下:
pga_aggregated_limit
解决方法
因此,首先,要回答您的问题-无法通过绑定变量提前实现这一点。您将需要在没有任何绑定变量条件的情况下实现查询,并且在实现视图中提供足够的数据以针对该条件评估绑定变量。
也就是说,
CREATE MATERIALIZED VIEW mat1 AS
SELECT ... all the data,no bind variables ...
并在运行时:
SELECT ... FROM mat1 WHERE ... bind variable conditions ...
您的查询有很多联接。 refresh fast on commit
的物化视图可能很困难。如果您具有Oracle 12.2,请查看实例化视图的ENABLE ON QUERY COMPUTATION
功能。基本上,您会定期刷新(可能每天或每隔几个小时刷新一次,具体取决于数据的(不稳定)程度以及查询运行的时间),但是Oracle仍会通过补充(稍微陈旧)来保证实时,新鲜的结果。 )的实例化视图数据与实例化视图日志中的数据。
总而言之,我暂时还不会去具体化。相反,我将根据不为空的条件切换到动态构建和执行查询。实际上,您给Oracle优化器带来了很大的压力,该优化器基本上只有两个工具可以很好地完成此工作:“ NVL-OR扩展”和绑定绑定游标。
这两种方法都为Oracle提供了一种方法,该方法可以根据为绑定变量指定的值来制定不同的执行计划。它们是很好的功能,但我只是认为您的查询可能会使他们完全信任我。如果存在已证明的问题,那就尤其如此。
诚然,如果您动态地构建和执行查询,这很痛苦,那么您将通过提交一堆更小,更集中,更易于优化的查询,使CBO的工作更加轻松。
当我说动态构建查询时,我的意思是这样的:
IF p_param_3rd_party_list IS NULL THEN
l_sql := l_sql || ' AND NVL(:23,''XXX'') IS NOT NULL';
l_sql := l_sql || ' AND NVL(:24,''XXX'') IS NOT NULL';
ELSE
-- I'm not bothering to convert all the single quotes to double quotes. Syntax won't
-- work,but you get the idea...
l_sql := l_sql || ' AND (supplier.thirdPartyNumber IN
( SELECT REGEXP_SUBSTR (NVL (:23,''),'[^,]+',1,LEVEL)
FROM DUAL
CONNECT BY REGEXP_SUBSTR (NVL (:24,LEVEL)
IS NOT NULL))
END IF;
EXECUTE IMMEDIATE l_sql USING ... all your bind variables
至关重要的是,即使出于可伸缩性原因而动态构建查询,仍要使用绑定变量(如上所示)。
当绑定变量为NULL时添加的虚拟条件点很重要,因此最终查询具有相同顺序的相同绑定变量列表,而与实际给出的参数无关。这样,您可以使用一个EXECUTE IMMEDIATE...USING...
命令来执行它。否则,这是一个巨大的痛苦。