您的查询执行三个任务:
1) 获取两个子集(12 和 14)的数据
2) 加入数据并
3) 将结果传递给客户端
请注意,索引访问(您怀疑会导致问题)仅与第 1 步相关。
所以要想得到更好的印象,首先要实现三个步骤之间经过的时间分布。
这可以使用 SQL*Plus 来完成(我使用的生成数据与我之前的答案相同)
数据访问
由于我的表没有索引,因此执行 count(*) 会执行 FULL TABLE SCAN。因此,在最坏的情况下,使用两倍的时间来获取数据。
SQL> set timi on
SQL> set autotrace on
SQL> select count(*) from mytab;
COUNT(*)
----------
20000
Elapsed: 00:00:01.13
Execution Plan
----------------------------------------------------------
Plan hash value: 3284627250
--------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
--------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 5472 (1)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | TABLE ACCESS FULL| MYTAB | 20000 | 5472 (1)| 00:00:01 |
--------------------------------------------------------------------
FTS 在大约一秒钟内就准备好了,所以要让两个组都差不多。两秒钟过去了。
加入
可以通过连接查询的 CTAS 模拟连接所用的时间。
SQL> create table myRes as
2 select a.SessionOrder rn0, b.SessionOrder rn1
3 from myTab a join myTab b on a.SessionOrder > b.SessionOrder and
4 a.something = 12 and b.something = 14;
Table created.
Elapsed: 00:00:23.65
Join 返回近 50M 行(由于大于条件),大约需要 21 秒(我为数据访问减去 2 秒)。
将数据传递给客户
我们使用选项set autotrace traceonly来抑制客户端屏幕上查询的输出,但是数据被传输了,所以我们可以
测量时间。 (如果把结果渲染到屏幕上,时间会长很多)
SQL> SET ARRAYSIZE 5000
SQL> set autotrace traceonly
SQL> select a.SessionOrder rn0, b.SessionOrder rn1
2 from myTab a join myTab b on a.SessionOrder > b.SessionOrder and
3 a.something = 12 and b.something = 14;
49995000 rows selected.
Elapsed: 00:03:03.89
Execution Plan
----------------------------------------------------------
Plan hash value: 2857240533
-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 49M| 667M| 11077 (2)| 00:00:01 |
| 1 | MERGE JOIN | | 49M| 667M| 11077 (2)| 00:00:01 |
| 2 | SORT JOIN | | 10000 | 70000 | 5473 (1)| 00:00:01 |
|* 3 | TABLE ACCESS FULL| MYTAB | 10000 | 70000 | 5472 (1)| 00:00:01 |
|* 4 | SORT JOIN | | 10000 | 70000 | 5473 (1)| 00:00:01 |
|* 5 | TABLE ACCESS FULL| MYTAB | 10000 | 70000 | 5472 (1)| 00:00:01 |
-----------------------------------------------------------------------------
这里花费最多的时间大约是 2:40 分钟
总结
因此,在总共 3 分钟以上的场景中,只有大约 2 秒用于数据访问(或大约 1%)。
即使您将数据访问减少到十分之一 - 您也几乎看不出有什么不同。
问题在于连接,甚至更多在于将数据传输到客户端。
何时索引可以提供帮助
当然这取决于...
在一个非常特殊的情况下,您有一个非常大的表,其中包含很少的数据 something in (12,14)
您可以从 AND SessionOrder 上定义的索引中获利。这允许使用 index only 访问完全绕过表访问的数据。