oracle - 查询成本 : Global Temporary Tables vs. 集合(虚拟数组)

标签 oracle performance oracle11g database-performance query-performance

我有一个查询,其结果存储在 GTT(全局临时表)和集合中。

再次从GTT中选取数据,得到一个很小的代价:103。

SELECT
    ...
FROM my_table_gtt
JOIN table2 ...
JOIN table3 ...

但是当将其从 GTT 切换到集合(VA - 虚拟数组)时,成本猛增 (78.000),但两者之间的执行时间差异非常小。

SELECT
    ...
FROM TABLE(CAST(my_table_va as my_table_tt))
JOIN table2 ...
JOIN table3 ...

我的问题是为什么这两种方法的成本差异如此之大?据我所知,GTT 不存储表统计信息,那么为什么它返回的成本比 VA 更好?

最佳答案

全局临时表可以像任何其他表一样具有统计信息。事实上,它们就像任何其他表一样,它们有数据段,只是在临时表空间中。

在 11g 中,统计信息是全局的,因此它们有时会导致执行计划出现问题。在 12c 中,它们是基于 session 的,因此每个 session 都会获得适当的 session (如果可用)。

集合类型基数基于 DB block 大小,默认 8 kB block 为 8168。集合内容存储在 PGA 中。在复杂查询中使用集合类型来提示优化器时,提示基数是很常见的。您还可以使用扩展的优化器接口(interface)来实现自己的成本计算方式。

编辑 - 添加测试:

CREATE TYPE STRINGTABLE IS TABLE OF VARCHAR2(255);
CREATE GLOBAL TEMPORARY TABLE TMP (VALUE VARCHAR2(255));

INSERT INTO TMP SELECT 'Value' || LEVEL FROM DUAL CONNECT BY LEVEL <= 1000000;

DECLARE
    x STRINGTABLE;
    cnt NUMBER;
BEGIN
    SELECT VALUE BULK COLLECT INTO x FROM TMP;

    DBMS_OUTPUT.PUT_LINE(TO_CHAR(SYSTIMESTAMP, 'MI:SS.FF3'));

    SELECT SUM(LENGTH(VALUE)) INTO cnt FROM TMP;

    DBMS_OUTPUT.PUT_LINE(TO_CHAR(SYSTIMESTAMP, 'MI:SS.FF3'));

    SELECT SUM(LENGTH(COLUMN_VALUE)) INTO cnt FROM TABLE(x);

    DBMS_OUTPUT.PUT_LINE(TO_CHAR(SYSTIMESTAMP, 'MI:SS.FF3'));
END;

在这种情况下,访问 GTT 的速度大约是收集速度的两倍,大约 200 毫秒,而在我的测试机器上为 400 毫秒。当我将行数增加到 10 000 000 时,我得到了 ORA-22813:操作数值超出了第二个查询的系统限制。

关于oracle - 查询成本 : Global Temporary Tables vs. 集合(虚拟数组),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32654069/

相关文章:

sql - Oracle - 如何对相关项目求和?

java - java 是否在 for 循环中缓存数组引用?

mysql - 从 JDBC 调用存储过程时的最佳实践

oracle10g - Oracle Express 11g 上的 "Get Started"错误

oracle - 收集另一个用户拥有的 PL/SQL 包的探查器信息

oracle - Liquibase 更新错误

c# - 替换 PL/SQL 中的特殊 XML 字符

Oracle RAC VIP 和 SCAN IP

java - Java 6 类加载速度有哪些?

oracle11g - Oracle 11g启动sqlplus的默认用户名和密码