Oracle SQL - 子查询工作正常,但是使用该子查询创建表似乎挂起

Posted

技术标签:

【中文标题】Oracle SQL - 子查询工作正常,但是使用该子查询创建表似乎挂起【英文标题】:Oracle SQL - Subquery Works fine, However Create Table with that subquery appears to hang 【发布时间】:2020-05-18 09:02:12 【问题描述】:

我有以下查询结构

CREATE TABLE <Table Name> AS 
(
   SELECT .... FROM ...
) 

当我自己运行 SELECT 语句时,它会在几秒钟内编译并返回结果。但是,当我使用 CREATE Table 语句运行它时,我认为它已经挂起并且永远不会编译。

这是什么原因?可以解决什么问题?

Oracle 数据库 12c

【问题讨论】:

【参考方案1】:

如果您在某些 GUI 中运行 SELECT,请注意它们中的大多数(如果不是全部)只返回几百行,而不是整个结果集。例如:如果您的查询确实返回了 2000 万行,GUI 会显示前 50 行(或 500,取决于您使用的工具),这有点令人困惑 - 就像它让您感到困惑一样。

如果您将当前查询用作内联视图,例如

select count(*)
from 
(select ... from ...)   --> this is your current query

它将“强制”Oracle 获取所有行,因此您会看到它实际需要多长时间。

除此之外,看看SELECT是否可以优化,例如

查看WHERE 子句中使用的列是否被索引 收集所有相关表的统计信息(用于FROM 子句) 删除ORDER BY子句(如果有的话;它与CTAS操作无关) 查看解释计划

性能调优远非我所建议的;这些只是您可能想要查看的一些建议。

【讨论】:

所以内部查询是围绕连接表和主表的所有索引设计的。我刚刚计算了所有行数及其大约 800k 行,并在一分钟内返回了它。我之前看过解释计划,并没有什么真正突出的成本高(但是我在这里的知识不是很好)没有按子句的顺序,所以这不是问题。【参考方案2】:

您是否尝试过直接加载插入,首先使用 CTAS 创建表,其中 1= 2,然后执行插入。这至少会告诉我们数据是否有问题(损坏的数据)或者是否是性能问题。

【讨论】:

【参考方案3】:

我之前也遇到过同样的问题,因为新数据太大(700 万行),我花了 3 个小时来执行代码。

我最好的建议是创建一个视图,因为它占用的空间更少,而不是一个新表。

【讨论】:

【参考方案4】:

所以这个问题的答案。

CREATE TABLE <Table Name> AS 
(
   SELECT foo 
   FROM baa
   LEFT JOIN 
   ( SELECT foo FROM baa WHERE DATES BETWEEN SYSDATE AND SYSDATE - 100 )
   WHERE DATES_1 BETWEEN SYSDATE - 10 AND SYSDATE - 100
)  

问题在于 BETWEEN 语句与同一时间段不匹配,并且子查询查看的数据多于主查询(我猜这是导致对表进行全面扫描?)

下面的查询有语句时间段之间的匹配,这在不到 3 分钟的时间内返回了结果。

CREATE TABLE <Table Name> AS 
(
   SELECT foo FROM baa
   LEFT JOIN ( SELECT foo FROM baa WHERE DATES BETWEEN SYSDATE - 10 AND SYSDATE - 100 )
   WHERE DATES_1 BETWEEN SYSDATE - 10 AND SYSDATE - 100
)  

【讨论】:

以上是关于Oracle SQL - 子查询工作正常,但是使用该子查询创建表似乎挂起的主要内容,如果未能解决你的问题,请参考以下文章

Oracle---SQL子查询---详解

为啥此相关子查询在 Oracle 和 SQL Server 中的工作方式不同

Oracle SQL 语言参考合并/子查询文档错误?

Oracle SQL 子查询——匹配多行

Oracle SQL 查询问题

ORACLE LEFT JOIN 子查询 在SQL SERVER中可以使用如图中的子查询,ORACLE中怎么实现