我在Oracle APEX中有一个应用程序,其中有很多页面项,有时我是从其他页面分配的,而大多数情况下它们是NULL,然后是一个交互式报表,该报表在一个很大的表上有一个SQL查询( 150k +行和30+列)。
SQL查询的结构如下
SELECT col1
, col2
, col3
, col4
FROM table
WHERE function(col1) IS NULL
AND (page_item1 = col1 OR page_item_1 IS NULL)
AND (page_item2 = col2 OR page_item_2 IS NULL)
.....
AND (page_item30 = col30 OR page_item_30 IS NULL)
如果项目为NULL,则此代码需要15秒才能运行并启动页面,因此我尝试对其进行优化。
然后我检查了一下,与页面项的AND是造成延迟的原因,而实际上并没有立即发生。
我认为这可能与OR子句的顺序有关,所以我将其更改为
SELECT col1
, col2
, col3
, col4
FROM table
WHERE function(col1) IS NULL
AND (page_item_1 IS NULL OR page_item1 = col1)
AND (page_item_2 IS NULL OR page_item2 = col2)
.....
AND (page_item_30 IS NULL OR page_item30 = col30)
但这并不能解决任何问题。这些项目是否为NULL仍需要15秒才能运行。
因此,我提出了一个修复程序,希望至少可以解决这个问题,这样,如果项目为NULL,它将很快。这不是一个完美的解决方案,但是我可以接受。
因此,我添加了另一个页面项目,其唯一功能是告诉我是否有任何项目不为NULL(将项目称为page_item_NULL)。
SELECT col1
, col2
, col3
, col4
FROM table
WHERE function(col1) IS NULL
AND page_item_NULL IS NULL OR (
(page_item_1 IS NULL OR page_item1 = col1)
AND (page_item_2 IS NULL OR page_item2 = col2)
.....
AND (page_item_30 IS NULL OR page_item30 = col30)
)
其背后的思考过程是,如果我知道页面项全部为NULL,则可以中止对页面项的检查。而且有效。但是效果比预期的好。
由于某种原因,这使得查询实际上是即时的,即使项目不是null。对于我来说,为什么应该这样做没有意义。
总结:
如果该项为NULL,则第一次查询需要15秒。
如果项为NULL但失败,则第二次查询旨在加快速度,无论哪种方式仍需15秒。
第三次查询,我实现了一个外部变量,以告诉我所有项目是否均为NULL,如果所有项目均为NULL,则停止所有检查。如果它们为NULL,这是一种尝试来加快它的速度,并且有效。除非它以某种方式加快了速度,即使它们不是NULL,我也不知道为什么。有更多经验的人都知道为什么吗?
编辑:想补充一下,只有col1是PK,如果我只检查
(page_item1 = col1 OR page_item_1 IS NULL)
它运行很快。当我获得15秒的加载时间时添加其他项目。