Sql CTE与子查询,哪一个是有效的?
这个查询对每一行执行子查询,对吗 现在如果我们有Sql CTE与子查询,哪一个是有效的?,sql,database,oracle,Sql,Database,Oracle,这个查询对每一行执行子查询,对吗 现在如果我们有 SELECT col, (SELECT COUNT(*) FROM table) as total_count FROM table 第二种方法会更有效吗?CTE是否只执行一次COUNT(*),然后选择将其用作准备值?或者在第二种情况下,也为每一行执行COUNT(*)?我相信Oracle和SQL Server中的查询优化器都会识别出COUNT查询不相关,计算一次,然后在执行外部查询的整个过程中使用缓存的结果 而且,据我所知,CTE不会改变任何东
SELECT col, (SELECT COUNT(*) FROM table) as total_count FROM table
第二种方法会更有效吗?CTE是否只执行一次
COUNT(*)
,然后选择将其用作准备值?或者在第二种情况下,也为每一行执行COUNT(*)
?我相信Oracle和SQL Server中的查询优化器都会识别出COUNT查询不相关,计算一次,然后在执行外部查询的整个过程中使用缓存的结果
而且,据我所知,CTE不会改变任何东西,因为在执行时,它内部的代码基本上只是内联到实际的外部查询中
下面是一个针对Oracle的示例,其中提到非相关子查询将执行一次并缓存,除非外部查询只有几行。在这种情况下,它可能不会被缓存,因为多次执行count子查询不会造成太大的损失。对于Oracle来说,最可靠的方法是使用扩展的统计信息观察语句的行为 首先将统计级别提高到
ALL
;WITH CTE(total_count) AS (
SELECT COUNT(*) FROM table
)
SELECT col, (SELECT total_count FROM CTE) FROM table;
然后运行两条语句(获取所有行)和
最后使用以下语句显示统计信息(传递正确的SQL\u ID):
这是我的测试表
select * from table(dbms_xplan.display_cursor('your SQL_ID here',null,'ALLSTATS LAST'));
及
因此,计划略有不同,但在这两种情况下,全表扫描
只启动一次(列开始=1)。这没什么区别
为了camparison的目的,我还运行了一个相关子查询,它提供了一个完全不同的图片,具有大量的启动(FTS)
您应该自己在数据上尝试,并告诉我们=)标记您正在使用的dbms。(不同的产品可能以不同的方式对此进行优化。)我基本上使用SQL Server或OracleSQL Server,Oracle以非常不同的方式优化CTE。答案可能因数据库而异。Gordon Linoff然后我选择Oracle)
select * from table(dbms_xplan.display_cursor('your SQL_ID here',null,'ALLSTATS LAST'));
SQL_ID 5n0sdcu8347j9, child number 0
-------------------------------------
SELECT col, (SELECT COUNT(*) FROM t1) as total_count FROM t1
Plan hash value: 1306093980
-------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1000 |00:00:00.01 | 351 |
| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.01 | 338 |
| 2 | TABLE ACCESS FULL| T1 | 1 | 1061 | 1000 |00:00:00.01 | 338 |
| 3 | TABLE ACCESS FULL | T1 | 1 | 1061 | 1000 |00:00:00.01 | 351 |
-------------------------------------------------------------------------------------
SQL_ID fs0h660f08bj6, child number 0
-------------------------------------
WITH CTE(total_count) AS ( SELECT COUNT(*) FROM t1 ) SELECT col,
(SELECT total_count FROM CTE) FROM t1
Plan hash value: 1223456497
--------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1000 |00:00:00.01 | 351 |
| 1 | VIEW | | 1 | 1 | 1 |00:00:00.01 | 338 |
| 2 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.01 | 338 |
| 3 | TABLE ACCESS FULL| T1 | 1 | 1061 | 1000 |00:00:00.01 | 338 |
| 4 | TABLE ACCESS FULL | T1 | 1 | 1061 | 1000 |00:00:00.01 | 351 |
--------------------------------------------------------------------------------------
SQL_ID cbvwd6pm6699m, child number 0
-------------------------------------
SELECT col, (SELECT COUNT(*) FROM t1 where col = a.col) as total_count
FROM t1 a
Plan hash value: 1306093980
-------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1000 |00:00:00.01 | 351 |
| 1 | SORT AGGREGATE | | 1000 | 1 | 1000 |00:00:00.31 | 338K|
|* 2 | TABLE ACCESS FULL| T1 | 1000 | 11 | 1000 |00:00:00.31 | 338K|
| 3 | TABLE ACCESS FULL | T1 | 1 | 1061 | 1000 |00:00:00.01 | 351 |
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("COL"=:B1)