使用表类型连接表会减慢计算速度?
Posted
技术标签:
【中文标题】使用表类型连接表会减慢计算速度?【英文标题】:Joining tables with table type slows down calculation? 【发布时间】:2019-08-30 08:03:56 【问题描述】:我有一个很大的计算,它将大约 10 个表连接在一起,并从结果中计算出一些值。我想编写一个函数,允许我用我作为输入参数提供的表(类型)替换连接的表之一(我们称之为表 A)。
我已经为表 A 定义了行和表类型
create or replace TYPE t_tableA_row AS OBJECT(*All Columns of Table A*);
create or replace TYPE t_tableA_table as TABLE OF t_tableA_row;
对于我需要作为函数输出的计算类型也是如此。 我的函数看起来像这样
create or replace FUNCTION calculation_VarInput (varTableA t_tableA_table)
RETURN t_calculationResult_table AS
result_ t_calculationResult_table;
BEGIN
SELECT t_calculationResult_row (*All Columns of Calculation Result*)
BULK COLLECT INTO result_
FROM (*The calculation*)
RETURN result_;
END;
如果我用只使用表 A(忽略输入参数)的正常计算来测试这个函数,它工作正常,大约需要 3 秒。但是,如果我将表 A 替换为 varTableA(作为表 A 的表类型的输入参数),计算需要很长时间,我从未见过它完成。
当我使用表 A 进行计算时,它看起来像这样
/*Inside the calculation*/
*a bunch tables being joined*
JOIN TableA A On A.Value = B.SomeOtherValue
JOIN *some other tables*
当我使用 varTableA 时
/*Inside the calculation*/
*a bunch tables being joined*
JOIN TABLE(varTableA ) A On A.Value = B.SomeOtherValue
JOIN *some other tables*
很抱歉没有发布确切的代码,但计算量很大,真的会让这篇文章变得臃肿。
任何想法为什么在加入时使用表类型会使计算与使用实际表相比要慢得多?
【问题讨论】:
通过将一些选择逻辑包装在一个函数中,您会从优化器中隐藏起来,这可能会导致它做出错误或低效的决策。它可能就像在table()
查询中包含一个/*+ cardinality */
一样简单,它准确地反映了函数结果集中的行数。但是很可能您需要在函数内重新编写选择,以便它可以很好地与查询的其余部分配合使用。或者也许只是保留原始查询 - 假设它工作正常并在 3 秒内返回?
感谢您的回答,但我不太明白。返回嵌套表中行数的基数函数如何帮助我的函数?如上所述,我的函数与我的原始查询几乎相同,它只是在进行计算之前替换了一些值。我需要在函数中执行此操作,因为我不想永久更改表中的值,我只想知道如果某些值不同,计算结果会是什么。所以我想我必须将它包含在一个函数中。网上有没有讨论这类问题的文章?
【参考方案1】:
您的函数在函数中封装了一些选择逻辑,因此对优化器隐藏了信息。这可能会导致优化器做出错误或低效的决策。
Oracle 已经收集了TableA
的统计信息,因此优化器知道它有多少行、索引了哪些列等等。因此,它可以找出表的最佳访问路径。它没有 TABLE(varTableA )
的统计信息,因此它假定它将返回 8192
(即 8k)行。如果说原来的TableA
返回了 8 行,这可能会改变执行计划。或 80000。您可以通过 running EXPLAIN PLAN for both versions of query 轻松检查。
如果这是问题所在,请在查询中添加 /*+ 基数 */,以准确反映函数结果集中的行数。提示(提示,而不是函数)告诉优化器它应该在计算中使用的行数。
我不想永久更改表中的值,我只想知道如果某些值不同,计算结果会是什么。
为什么不使用视图呢?从TableA
中选择并在其投影中应用所需修改的简单视图。当然,我对您的数据以及您想如何操作它一无所知,因此由于各种原因,这可能是不切实际的。但这是我要开始的地方。
【讨论】:
我无法通过基数提示终止它,但是,使用视图而不是表类型有效!它仍然有点慢,但它现在终止了 用视图调优比表更难,因为我们不能将谓词推送到视图的 WHERE 子句中。所以我们不能利用连接产生的任何TableA
过滤——优化器很聪明,但不是那么聪明。还没有!以上是关于使用表类型连接表会减慢计算速度?的主要内容,如果未能解决你的问题,请参考以下文章
在某些情况下,为什么CTE(公用表表达式)与SQL Server中的临时表相比会减慢查询速度