热门标签 | HotTags
当前位置:  开发笔记 > 数据库 > 正文

如何访问索引最大最小值min/maxscan

??访问索引的最大和最小值,ORACLE做了哪些优化呢?不同的版本是否有限制呢?索引是有序存储的,因此,获取索引的最大值,只需要扫描最右(最左desc索引)叶子块,最小值,只需要扫描最左(最右desc索引)叶子块即可,在RBO中就有这种优化访问路径了。见下

?? 访问索引的最大和最小值,ORACLE做了哪些优化呢?不同的版本是否有限制呢?索引是有序存储的,因此,获取索引的最大值,只需要扫描最右(最左desc索引)叶子块,最小值,只需要扫描最左(最右desc索引)叶子块即可,在RBO中就有这种优化访问路径了。见下

?? 访问索引的最大和最小值,ORACLE做了哪些优化呢?不同的版本是否有限制呢?索引是有序存储的,因此,获取索引的最大值,只需要扫描最右(最左desc索引)叶子块,最小值,只需要扫描最左(最右desc索引)叶子块即可,在RBO中就有这种优化访问路径了。见下图(摘自ORACLE 11G CONCEPTS):

如下例:
单独访问MAX,MIN,可以走INDEX FULL SCAN MIN/MAX访问路径

dingjun123@ORADB> show rel
release 1102000100

DROP TABLE t;
CREATE TABLE t AS SELECT * FROM dba_objects;
CREATE INDEX idx_t ON t(object_id);

dingjun123@ORADB> SELECT MAX(object_id) FROM t;
1 row selected.

Execution Plan
———————————————————-
Plan hash value: 3689784082
————————————————————————————
| Id ?| Operation ? ? ? ? ? ? ? ? ?| Name ?| Rows ?| Bytes | Cost (%CPU)| Time ? ? |
————————————————————————————
| ? 0 | SELECT STATEMENT ? ? ? ? ? | ? ? ? | ? ? 1 | ? ?13 | ? ? 2 ? (0)| 00:00:01 |
| ? 1 | ?SORT AGGREGATE ? ? ? ? ? ?| ? ? ? | ? ? 1 | ? ?13 | ? ? ? ? ? ?| ? ? ? ? ?|
| ? 2 | ??INDEX FULL SCAN (MIN/MAX)| IDX_T | ? ? 1 | ? ?13 | ? ? 2 ? (0)| 00:00:01 |
————————————————————————————
Note
—–
? ?- dynamic sampling used for this statement (level=2)

Statistics
———————————————————-
? ? ? ? ? 0 ?recursive calls
? ? ? ? ? 0 ?db block gets
? ? ? ? ? 2 ?consistent gets
? ? ? ? ? 0 ?physical reads
? ? ? ? ? 0 ?redo size
? ? ? ? 430 ?bytes sent via SQL*Net to client
? ? ? ? 415 ?bytes received via SQL*Net from client
? ? ? ? ? 2 ?SQL*Net roundtrips to/from client
? ? ? ? ? 0 ?sorts (memory)
? ? ? ? ? 0 ?sorts (disk)
? ? ? ? ? 1 ?rows processed

dingjun123@ORADB> SELECT MIN(object_id) FROM t;
1 row selected.

Execution Plan
———————————————————-
Plan hash value: 3689784082
————————————————————————————
| Id ?| Operation ? ? ? ? ? ? ? ? ?| Name ?| Rows ?| Bytes | Cost (%CPU)| Time ? ? |
————————————————————————————
| ? 0 | SELECT STATEMENT ? ? ? ? ? | ? ? ? | ? ? 1 | ? ?13 | ? ? 2 ? (0)| 00:00:01 |
| ? 1 | ?SORT AGGREGATE ? ? ? ? ? ?| ? ? ? | ? ? 1 | ? ?13 | ? ? ? ? ? ?| ? ? ? ? ?|
| ? 2 | ??INDEX FULL SCAN (MIN/MAX)| IDX_T | ? ? 1 | ? ?13 | ? ? 2 ? (0)| 00:00:01 |
————————————————————————————

Note
—–
? ?- dynamic sampling used for this statement (level=2)

Statistics
———————————————————-
? ? ? ? ? 0 ?recursive calls
? ? ? ? ? 0 ?db block gets
? ? ? ? ? 2 ?consistent gets
? ? ? ? ? 0 ?physical reads
? ? ? ? ? 0 ?redo size
? ? ? ? 428 ?bytes sent via SQL*Net to client
? ? ? ? 415 ?bytes received via SQL*Net from client
? ? ? ? ? 2 ?SQL*Net roundtrips to/from client
? ? ? ? ? 0 ?sorts (memory)
? ? ? ? ? 0 ?sorts (disk)
? ? ? ? ? 1 ?rows processed


通过这种高效的访问路径,只需要扫描最左或最右边的一个叶子块即可,只找1行数据,上面统计信息显示只需要2个IO就搞定了。如果要一条SQL同时获得MIN/MAX呢?

–先收集统计信息
dingjun123@ORADB> EXEC dbms_stats.gather_table_stats(ownname => USER,tabname => ‘t’,estimate_percent => 100,cascade => TRUE);
PL/SQL procedure successfully completed.

?

dingjun123@ORADB> SELECT MAX(object_id) max_obj,MIN(OBJECT_id) min_obj FROM t;
1 row selected.

Execution Plan
———————————————————-
Plan hash value: 2966233522
—————————————————————————
| Id ?| Operation ? ? ? ? ?| Name | Rows ?| Bytes | Cost (%CPU)| Time ? ? |
—————————————————————————
| ? 0 | SELECT STATEMENT ? | ? ? ?| ? ? 1 | ? ?13 | ? 299 ? (1)| 00:00:04 |
| ? 1 | ?SORT AGGREGATE ? ?| ? ? ?| ? ? 1 | ? ?13 | ? ? ? ? ? ?| ? ? ? ? ?|
| ? 2 | ??TABLE ACCESS FULL| T ? ?| 75885 | ? 963K| ? 299 ? (1)| 00:00:04 |
—————————————————————————

? ? 竟然走的全表扫描,很显然,我这里的索引,是比表小很多,应该只访问索引就可以了,虽然object_id无NOT NULL约束,但是max/min(列)运算已经告之ORACLE,这里肯定不包含NULL,但是:

dingjun123@ORADB> SELECT MAX(object_id) max_obj,MIN(OBJECT_id) min_obj FROM t?WHERE object_id IS NOT NULL;
1 row selected.

Execution Plan
———————————————————-
Plan hash value: 2371838348
——————————————————————————-
| Id ?| Operation ? ? ? ? ? ? | Name ?| Rows ?| Bytes | Cost (%CPU)| Time ? ? |
——————————————————————————-
| ? 0 | SELECT STATEMENT ? ? ?| ? ? ? | ? ? 1 | ? ? 5 | ? ?48 ? (3)| 00:00:01 |
| ? 1 | ?SORT AGGREGATE ? ? ? | ? ? ? | ? ? 1 | ? ? 5 | ? ? ? ? ? ?| ? ? ? ? ?|
|* ?2 | ??INDEX FAST FULL SCAN| IDX_T | 75263 | ? 367K| ? ?48 ? (3)| 00:00:01 |
——————————————————————————-
Predicate Information (identified by operation id):
—————————————————
? ?2 – filter(“OBJECT_ID” IS NOT NULL)

? ? 显式加WHERE OBJECT_ID IS NOT NULL告诉ORACLE,那么计划改变,走INDEX FAST FULL SCAN,这是正确的。这可以认定是此版本下ORACLE优化器的一个限制。通过实验发现,单个组函数对索引运算,可以走索引,但是2个或以上的就不行了。

–单个组函数对索引运算,走索引
dingjun123@ORADB> SELECT SUM(object_id) ?FROM t;
Execution Plan
———————————————————-
Plan hash value: 2371838348
——————————————————————————-
| Id ?| Operation ? ? ? ? ? ? | Name ?| Rows ?| Bytes | Cost (%CPU)| Time ? ? |
——————————————————————————-
| ? 0 | SELECT STATEMENT ? ? ?| ? ? ? | ? ? 1 | ? ? 5 | ? ?48 ? (3)| 00:00:01 |
| ? 1 | ?SORT AGGREGATE ? ? ? | ? ? ? | ? ? 1 | ? ? 5 | ? ? ? ? ? ?| ? ? ? ? ?|
| ? 2 | ??INDEX FAST FULL SCAN| IDX_T | 75264 | ? 367K| ? ?48 ? (3)| 00:00:01 |
——————————————————————————-

–多个组函数对索引运算,不走索引,需要NOT NULL约束或手动加IS NOT NULL条件
dingjun123@ORADB> SELECT SUM(object_id) ?,count(object_id) FROM t ;
Execution Plan
———————————————————-
Plan hash value: 2966233522
—————————————————————————
| Id ?| Operation ? ? ? ? ?| Name | Rows ?| Bytes | Cost (%CPU)| Time ? ? |
—————————————————————————
| ? 0 | SELECT STATEMENT ? | ? ? ?| ? ? 1 | ? ? 5 | ? 299 ? (1)| 00:00:04 |
| ? 1 | ?SORT AGGREGATE ? ?| ? ? ?| ? ? 1 | ? ? 5 | ? ? ? ? ? ?| ? ? ? ? ?|
| ? 2 | ??TABLE ACCESS FULL| T ? ?| 75264 | ? 367K| ? 299 ? (1)| 00:00:04 |
—————————————————————————

–无NOT NULL,使用HINT也是失效的
dingjun123@ORADB> SELECT/*+index(t)*/ SUM(object_id) ?,count(object_id) FROM t ;
Execution Plan
———————————————————-
Plan hash value: 2966233522
—————————————————————————
| Id ?| Operation ? ? ? ? ?| Name | Rows ?| Bytes | Cost (%CPU)| Time ? ? |
—————————————————————————
| ? 0 | SELECT STATEMENT ? | ? ? ?| ? ? 1 | ? ? 5 | ? 299 ? (1)| 00:00:04 |
| ? 1 | ?SORT AGGREGATE ? ?| ? ? ?| ? ? 1 | ? ? 5 | ? ? ? ? ? ?| ? ? ? ? ?|
| ? 2 | ??TABLE ACCESS FULL| T ? ?| 75264 | ? 367K| ? 299 ? (1)| 00:00:04 |
—————————————————————————

?

dingjun123@ORADB> SELECT SUM(object_id) ?,count(object_id) FROM t?WHERE object_id IS NOT NULL;
Execution Plan
———————————————————-
Plan hash value: 2371838348
——————————————————————————-
| Id ?| Operation ? ? ? ? ? ? | Name ?| Rows ?| Bytes | Cost (%CPU)| Time ? ? |
——————————————————————————-
| ? 0 | SELECT STATEMENT ? ? ?| ? ? ? | ? ? 1 | ? ? 5 | ? ?48 ? (3)| 00:00:01 |
| ? 1 | ?SORT AGGREGATE ? ? ? | ? ? ? | ? ? 1 | ? ? 5 | ? ? ? ? ? ?| ? ? ? ? ?|
|* ?2 | ??INDEX FAST FULL SCAN| IDX_T | 75263 | ? 367K| ? ?48 ? (3)| 00:00:01 |
——————————————————————————-
Predicate Information (identified by operation id):
—————————————————
? ?2 – filter(“OBJECT_ID” IS NOT NULL)

–多个组函数实验,省略,当然多个组函数

? ? ??那么这种情况下,ORACLE为什么不走INDEX FULL?MIN/MAX呢,很显然SELECT MIN,MAX… FROM 是不行的。可以转换一下思路:既然单个组函数操作,可以走索引,特别是MIN,MAX的操作,可以高效走INDEX FULL MIN,MAX,那么就可以使用2条SQL,然后合并即可:

–使用UNION ALL,缺点,不能直接知道谁大谁小,还得进一步运算
–访问2次索引,使用的都是FULL MIN/MAX路径,因此IO增加1倍,4个IO

dingjun123@ORADB> SELECT MIN(object_id) FROM t
? 2 ?UNION ALL
? 3 ?SELECT MAX(object_id) FROM t;

2 rows selected.

Execution Plan
———————————————————-
Plan hash value: 2039144771
————————————————————————————-
| Id ?| Operation ? ? ? ? ? ? ? ? ? | Name ?| Rows ?| Bytes | Cost (%CPU)| Time ? ? |
————————————————————————————-
| ? 0 | SELECT STATEMENT ? ? ? ? ? ?| ? ? ? | ? ? 2 | ? ?10 | ? ? 4 ?(50)| 00:00:01 |
| ? 1 |??UNION-ALL?? ? ? ? ? ? ? ? ?| ? ? ? | ? ? ? | ? ? ? | ? ? ? ? ? ?| ? ? ? ? ?|
| ? 2 | ? SORT AGGREGATE ? ? ? ? ? ?| ? ? ? | ? ? 1 | ? ? 5 | ? ? ? ? ? ?| ? ? ? ? ?|
| ? 3 | ? ?INDEX FULL SCAN (MIN/MAX)| IDX_T | ? ? 1 | ? ? 5 | ? ? 2 ? (0)| 00:00:01 |
| ? 4 | ? SORT AGGREGATE ? ? ? ? ? ?| ? ? ? | ? ? 1 | ? ? 5 | ? ? ? ? ? ?| ? ? ? ? ?|
| ? 5 | ? ?INDEX FULL SCAN (MIN/MAX)| IDX_T | ? ? 1 | ? ? 5 | ? ? 2 ? (0)| 00:00:01 |
————————————————————————————-

Statistics
———————————————————-
? ? ? ? ? 0 ?recursive calls
? ? ? ? ? 0 ?db block gets
? ? ? ? ? 4 ?consistent gets
? ? ? ? ? 0 ?physical reads
? ? ? ? ? 0 ?redo size
? ? ? ? 468 ?bytes sent via SQL*Net to client
? ? ? ? 415 ?bytes received via SQL*Net from client
? ? ? ? ? 2 ?SQL*Net roundtrips to/from client
? ? ? ? ? 0 ?sorts (memory)
? ? ? ? ? 0 ?sorts (disk)
? ? ? ? ? 2 ?rows processed

–使用标量子查询,好处,最大哪个列是最大值,哪个列是最小值
dingjun123@ORADB> SELECT (SELECT MIN(object_id) from t) min_obj,
? 2 ?(SELECT MAX(object_id) FROM t) max_obj
? 3 ?FROM dual;
1 row selected.

Execution Plan
———————————————————-
Plan hash value: 3635878085
————————————————————————————
| Id ?| Operation ? ? ? ? ? ? ? ? ?| Name ?| Rows ?| Bytes | Cost (%CPU)| Time ? ? |
————————————————————————————
| ? 0 | SELECT STATEMENT ? ? ? ? ? | ? ? ? | ? ? 1 | ? ? ? | ? ? 2 ? (0)| 00:00:01 |
| ? 1 | ?SORT AGGREGATE ? ? ? ? ? ?| ? ? ? | ? ? 1 | ? ? 5 | ? ? ? ? ? ?| ? ? ? ? ?|
| ? 2 | ? INDEX FULL SCAN (MIN/MAX)| IDX_T | ? ? 1 | ? ? 5 | ? ? 2 ? (0)| 00:00:01 |
| ? 3 | ?SORT AGGREGATE ? ? ? ? ? ?| ? ? ? | ? ? 1 | ? ? 5 | ? ? ? ? ? ?| ? ? ? ? ?|
| ? 4 | ? INDEX FULL SCAN (MIN/MAX)| IDX_T | ? ? 1 | ? ? 5 | ? ? 2 ? (0)| 00:00:01 |
| ? 5 | ?FAST DUAL ? ? ? ? ? ? ? ? | ? ? ? | ? ? 1 | ? ? ? | ? ? 2 ? (0)| 00:00:01 |
————————————————————————————

Statistics
———————————————————-
? ? ? ? ? 1 ?recursive calls
? ? ? ? ? 0 ?db block gets
? ? ? ? ? 4 ?consistent gets
? ? ? ? ? 0 ?physical reads
? ? ? ? ? 0 ?redo size
? ? ? ? 487 ?bytes sent via SQL*Net to client
? ? ? ? 415 ?bytes received via SQL*Net from client
? ? ? ? ? 2 ?SQL*Net roundtrips to/from client
? ? ? ? ? 0 ?sorts (memory)
? ? ? ? ? 0 ?sorts (disk)
? ? ? ? ? 1 ?rows processed

? ? 第一种UNION ALL方式可以行列转换一下:

dingjun123@ORADB> SELECT MAX(decode(rn,1,val)) min_obj, MAX(decode(rn,2,val)) max_obj
? 2 ?FROM (
? 3 ?SELECT MIN(object_id) val,1 rn FROM t
? 4 ?UNION ALL
? 5 ?SELECT MAX(object_id),2 rn FROM t
? 6 ?);

? ?MIN_OBJ ? ?MAX_OBJ
———- ———-
? ? ? ? ?2 ? ? 108164

? ?下面举一个实例说明INDEX FULL SCAN MIN/MAX的使用:
需求:查询出最小OBJECT_ID的所有信息。用多种方法实现:

–先将object_id变为NOT NULL约束
DELETE FROM t WHERE object_id IS NULL;
ALTER TABLE t MODIFY object_id NOT NULL;

–1.分析函数,因为OBJECT_ID有索引,11G的分页函数也可以谓词推进,如果走索引可以WINDOW NOSORT STOPKEY,效率不错,5个IO
dingjun123@ORADB> SELECT *
? 2 ?FROM (
? 3 ?SELECT t.*,row_number() over(ORDER BY object_id) rn
? 4 ?FROM t
? 5 ?) WHERE rn=1;
1 row selected.

Execution Plan
———————————————————-
Plan hash value: 233755475
—————————————————————————————
| Id ?| Operation ? ? ? ? ? ? ? ? ? ? | Name ?| Rows ?| Bytes | Cost (%CPU)| Time ? ? |
—————————————————————————————
| ? 0 | SELECT STATEMENT ? ? ? ? ? ? ?| ? ? ? | 75264 | ? ?15M| ?1478 ? (1)| 00:00:18 |
|* ?1 | ?VIEW ? ? ? ? ? ? ? ? ? ? ? ? | ? ? ? | 75264 | ? ?15M| ?1478 ? (1)| 00:00:18 |
|* ?2 | ??WINDOW NOSORT STOPKEY?? ? ? | ? ? ? | 75264 | ?7129K| ?1478 ? (1)| 00:00:18 |
| ? 3 | ? ?TABLE ACCESS BY INDEX ROWID| T ? ? | 75264 | ?7129K| ?1478 ? (1)| 00:00:18 |
| ? 4 | ? ? INDEX FULL SCAN ? ? ? ? ? | IDX_T | 75264 | ? ? ? | ? 169 ? (1)| 00:00:03 |
—————————————————————————————
Predicate Information (identified by operation id):
—————————————————
? ?1 – filter(“RN”=1)
? ?2 &#8211; filter(ROW_NUMBER() OVER ( ORDER BY &#8220;OBJECT_ID&#8221;)<=1)
Statistics
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
? ? ? ? ? 0 ?recursive calls
? ? ? ? ? 0 ?db block gets
? ? ? ? ??5 ?consistent gets
? ? ? ? ? 0 ?physical reads
? ? ? ? ? 0 ?redo size
? ? ? ?1451 ?bytes sent via SQL*Net to client
? ? ? ? 415 ?bytes received via SQL*Net from client
? ? ? ? ? 2 ?SQL*Net roundtrips to/from client
? ? ? ? ? 0 ?sorts (memory)
? ? ? ? ? 0 ?sorts (disk)
? ? ? ? ? 1 ?rows processed

&#8211;2.使用传统分页ROWNUM,走STOPKEY,3个IO,效率最好
dingjun123@ORADB> SELECT x.*
? 2 ?FROM (
? 3 ?SELECT * FROM t ORDER BY object_id
? 4 ?) x WHERE ROWNUM=1;
1 row selected.

Execution Plan
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
Plan hash value: 3436459561
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;
| Id ?| Operation ? ? ? ? ? ? ? ? ? ? | Name ?| Rows ?| Bytes | Cost (%CPU)| Time ? ? |
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;
| ? 0 | SELECT STATEMENT ? ? ? ? ? ? ?| ? ? ? | ? ? 1 | ? 207 | ? ? 3 ? (0)| 00:00:01 |
|* ?1 | ?COUNT STOPKEY ? ? ? ? ? ? ? ?| ? ? ? | ? ? ? | ? ? ? | ? ? ? ? ? ?| ? ? ? ? ?|
| ? 2 | ? VIEW ? ? ? ? ? ? ? ? ? ? ? ?| ? ? ? | ? ? 1 | ? 207 | ? ? 3 ? (0)| 00:00:01 |
| ? 3 | ? ?TABLE ACCESS BY INDEX ROWID| T ? ? | 75264 | ?7129K| ? ? 3 ? (0)| 00:00:01 |
| ? 4 | ? ? INDEX FULL SCAN ? ? ? ? ? | IDX_T | ? ? 1 | ? ? ? | ? ? 2 ? (0)| 00:00:01 |
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;
Predicate Information (identified by operation id):
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;
? ?1 &#8211; filter(ROWNUM=1)

Statistics
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
? ? ? ? ? 0 ?recursive calls
? ? ? ? ? 0 ?db block gets
? ? ? ? ??3 ?consistent gets
? ? ? ? ? 0 ?physical reads
? ? ? ? ? 0 ?redo size
? ? ? ?1392 ?bytes sent via SQL*Net to client
? ? ? ? 415 ?bytes received via SQL*Net from client
? ? ? ? ? 2 ?SQL*Net roundtrips to/from client
? ? ? ? ? 0 ?sorts (memory)
? ? ? ? ? 0 ?sorts (disk)
? ? ? ? ? 1 ?rows processed

&#8211;3.子查询实现,子查询走高效的FULL INDEX SCAN?MIN MAX,外部查询条件又是OBJECT_ID,走INDEX RANGE SCAN,6个IO,效率比上面的差,但是不算太差
dingjun123@ORADB> SELECT * FROM t
? 2 ?WHERE t.object_id=
? 3 ?(SELECT MIN(object_id) FROM t);
1 row selected.

Execution Plan
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
Plan hash value: 72615852
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;
| Id ?| Operation ? ? ? ? ? ? ? ? ? ?| Name ? | Rows ?| Bytes | Cost (%CPU)| Time ? ? |
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;
| ? 0 | SELECT STATEMENT ? ? ? ? ? ? | ? ? ? ?| ? ? 1 | ? ?97 | ? ? 4 ? (0)| 00:00:01 |
| ? 1 | ?TABLE ACCESS BY INDEX ROWID | T ? ? ?| ? ? 1 | ? ?97 | ? ? 2 ? (0)| 00:00:01 |
|* ?2 | ? INDEX RANGE SCAN ? ? ? ? ? | IDX_T ?| ? ? 1 | ? ? ? | ? ? 1 ? (0)| 00:00:01 |
| ? 3 | ? ?SORT AGGREGATE ? ? ? ? ? ?| ? ? ? ?| ? ? 1 | ? ? 5 | ? ? ? ? ? ?| ? ? ? ? ?|
| ? 4 | ? ? INDEX FULL SCAN (MIN/MAX)| IDX1_T | ? ? 1 | ? ? 5 | ? ? 2 ? (0)| 00:00:01 |
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;
Predicate Information (identified by operation id):
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;

? ?2 &#8211; access(&#8220;T&#8221;.&#8221;OBJECT_ID&#8221;= (SELECT MIN(&#8220;OBJECT_ID&#8221;) FROM &#8220;T&#8221; &#8220;T&#8221;))

Statistics
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
? ? ? ? ? 0 ?recursive calls
? ? ? ? ? 0 ?db block gets
? ? ? ? ??6 ?consistent gets
? ? ? ? ? 0 ?physical reads
? ? ? ? ? 0 ?redo size
? ? ? ?1392 ?bytes sent via SQL*Net to client
? ? ? ? 415 ?bytes received via SQL*Net from client
? ? ? ? ? 2 ?SQL*Net roundtrips to/from client
? ? ? ? ? 0 ?sorts (memory)
? ? ? ? ? 0 ?sorts (disk)
? ? ? ? ? 1 ?rows processed

? ? 当然,如果要同时找最大最小值索引的全部信息

&#8211;不能图方便,不是简单的SQL就是好的SQL,无法走STOP KEY和降序索引扫描,逻辑读1474
dingjun123@ORADB> SELECT *
? 2 ?FROM (
? 3 ?SELECT t.*,row_number() over(ORDER BY object_id) rn1,
? 4 ?row_number() over(ORDER BY object_id DESC) rn2
? 5 ?FROM t
? 6 ?) WHERE rn1=1 OR rn2=1;
2 rows selected.

Execution Plan
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
Plan hash value: 1020799068
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;
| Id ?| Operation ? ? ? ? ? ? ? ? ? ? ?| Name ?| Rows ?| Bytes |TempSpc| Cost (%CPU)| Time ? ? |
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;
| ? 0 | SELECT STATEMENT ? ? ? ? ? ? ? | ? ? ? | 75264 | ? ?16M| ? ? ? | ?3149 ? (1)| 00:00:38 |
|* ?1 | ?VIEW ? ? ? ? ? ? ? ? ? ? ? ? ?| ? ? ? | 75264 | ? ?16M| ? ? ? | ?3149 ? (1)| 00:00:38 |
| ? 2 | ? WINDOW SORT ? ? ? ? ? ? ? ? ?| ? ? ? | 75264 | ?7129K| ?9880K| ?3149 ? (1)| 00:00:38 |
| ? 3 | ? ?WINDOW NOSORT ? ? ? ? ? ? ? | ? ? ? | 75264 | ?7129K| ? ? ? | ?3149 ? (1)| 00:00:38 |
| ? 4 | ? ? TABLE ACCESS BY INDEX ROWID| T ? ? | 75264 | ?7129K| ? ? ? | ?1478 ? (1)| 00:00:18 |
| ? 5 | ? ? ?INDEX FULL SCAN ? ? ? ? ? | IDX_T | 75264 | ? ? ? | ? ? ? | ? 169 ? (1)| 00:00:03 |
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;

Predicate Information (identified by operation id):
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;
? ?1 &#8211; filter(&#8220;RN1&#8243;=1 OR &#8220;RN2&#8243;=1)

Statistics
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
? ? ? ? ? 0 ?recursive calls
? ? ? ? ? 0 ?db block gets
? ? ???1474 ?consistent gets
? ? ? ? ? 0 ?physical reads
? ? ? ? ? 0 ?redo size
? ? ? ?1639 ?bytes sent via SQL*Net to client
? ? ? ? 415 ?bytes received via SQL*Net from client
? ? ? ? ? 2 ?SQL*Net roundtrips to/from client
? ? ? ? ? 1 ?sorts (memory)
? ? ? ? ? 0 ?sorts (disk)
? ? ? ? ? 2 ?rows processed

&#8211;使用UNION ALL,两条语句都很高效,后面的可以走DESC扫描并STOP KEY,逻辑读8
dingjun123@ORADB> SELECT *
? 2 ?FROM (
? 3 ?SELECT t.*,row_number() over(ORDER BY object_id) rn
? 4 ?FROM t
? 5 ?) WHERE rn=1
? 6 ?UNION ALL
? 7 ?SELECT *
? 8 ?FROM (
? 9 ?SELECT t.*,row_number() over(ORDER BY object_id DESC) rn
?10 ?FROM t
?11 ?) WHERE rn=1;
2 rows selected.

Execution Plan
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
Plan hash value: 4213848416
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
| Id ?| Operation ? ? ? ? ? ? ? ? ? ? ?| Name ?| Rows ?| Bytes | Cost (%CPU)| Time ? ? |
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
| ? 0 | SELECT STATEMENT ? ? ? ? ? ? ? | ? ? ? | ? 150K| ? ?31M| ?2955 ?(51)| 00:00:36 |
| ? 1 | ?UNION-ALL ? ? ? ? ? ? ? ? ? ? | ? ? ? | ? ? ? | ? ? ? | ? ? ? ? ? ?| ? ? ? ? ?|
|* ?2 | ? VIEW ? ? ? ? ? ? ? ? ? ? ? ? | ? ? ? | 75264 | ? ?15M| ?1478 ? (1)| 00:00:18 |
|* ?3 | ? ?WINDOW NOSORT STOPKEY ? ? ? | ? ? ? | 75264 | ?7129K| ?1478 ? (1)| 00:00:18 |
| ? 4 | ? ? TABLE ACCESS BY INDEX ROWID| T ? ? | 75264 | ?7129K| ?1478 ? (1)| 00:00:18 |
| ? 5 | ? ? ?INDEX FULL SCAN ? ? ? ? ? | IDX_T | 75264 | ? ? ? | ? 169 ? (1)| 00:00:03 |
|* ?6 | ? VIEW ? ? ? ? ? ? ? ? ? ? ? ? | ? ? ? | 75264 | ? ?15M| ?1478 ? (1)| 00:00:18 |
|* ?7 | ? ?WINDOW NOSORT STOPKEY ? ? ? | ? ? ? | 75264 | ?7129K| ?1478 ? (1)| 00:00:18 |
| ? 8 | ? ? TABLE ACCESS BY INDEX ROWID| T ? ? | 75264 | ?7129K| ?1478 ? (1)| 00:00:18 |
| ? 9 | ? ? ?INDEX FULL SCAN DESCENDING| IDX_T | 75264 | ? ? ? | ? 169 ? (1)| 00:00:03 |
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
Predicate Information (identified by operation id):
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;
? ?2 &#8211; filter(&#8220;RN&#8221;=1)
? ?3 &#8211; filter(ROW_NUMBER() OVER ( ORDER BY &#8220;OBJECT_ID&#8221;)<=1)
? ?6 &#8211; filter(&#8220;RN&#8221;=1)
? ?7 &#8211; filter(ROW_NUMBER() OVER ( ORDER BY INTERNAL_FUNCTION(&#8220;OBJECT_ID&#8221;) DESC
? ? ? ? ? ? ? )<=1)
Statistics
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
? ? ? ? ? 0 ?recursive calls
? ? ? ? ? 0 ?db block gets
? ? ? ??? 8 ?consistent gets
? ? ? ? ? 0 ?physical reads
? ? ? ? ? 0 ?redo size
? ? ? ?1571 ?bytes sent via SQL*Net to client
? ? ? ? 415 ?bytes received via SQL*Net from client
? ? ? ? ? 2 ?SQL*Net roundtrips to/from client
? ? ? ? ? 0 ?sorts (memory)
? ? ? ? ? 0 ?sorts (disk)
? ? ? ? ? 2 ?rows processed

&#8211;传统ROWNUM分页UNION ALL,效率最好,逻辑读6
dingjun123@ORADB> SELECT x.*
? 2 ?FROM (
? 3 ?SELECT * FROM t ORDER BY object_id
? 4 ?) x WHERE ROWNUM=1
? 5 ?UNION ALL
? 6 ?SELECT x.*
? 7 ?FROM (
? 8 ?SELECT * FROM t ORDER BY object_id DESC
? 9 ?) x WHERE ROWNUM=1;
2 rows selected.

Execution Plan
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
Plan hash value: 1989929593
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
| Id ?| Operation ? ? ? ? ? ? ? ? ? ? ?| Name ?| Rows ?| Bytes | Cost (%CPU)| Time ? ? |
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
| ? 0 | SELECT STATEMENT ? ? ? ? ? ? ? | ? ? ? | ? ? 2 | ? 414 | ?2955 ?(51)| 00:00:36 |
| ? 1 | ?UNION-ALL ? ? ? ? ? ? ? ? ? ? | ? ? ? | ? ? ? | ? ? ? | ? ? ? ? ? ?| ? ? ? ? ?|
|* ?2 | ? COUNT STOPKEY ? ? ? ? ? ? ? ?| ? ? ? | ? ? ? | ? ? ? | ? ? ? ? ? ?| ? ? ? ? ?|
| ? 3 | ? ?VIEW ? ? ? ? ? ? ? ? ? ? ? ?| ? ? ? | 75264 | ? ?14M| ?1478 ? (1)| 00:00:18 |
| ? 4 | ? ? TABLE ACCESS BY INDEX ROWID| T ? ? | 75264 | ?7129K| ?1478 ? (1)| 00:00:18 |
| ? 5 | ? ? ?INDEX FULL SCAN ? ? ? ? ? | IDX_T | 75264 | ? ? ? | ? 169 ? (1)| 00:00:03 |
|* ?6 | ? COUNT STOPKEY ? ? ? ? ? ? ? ?| ? ? ? | ? ? ? | ? ? ? | ? ? ? ? ? ?| ? ? ? ? ?|
| ? 7 | ? ?VIEW ? ? ? ? ? ? ? ? ? ? ? ?| ? ? ? | 75264 | ? ?14M| ?1478 ? (1)| 00:00:18 |
| ? 8 | ? ? TABLE ACCESS BY INDEX ROWID| T ? ? | 75264 | ?7129K| ?1478 ? (1)| 00:00:18 |
| ? 9 | ? ? ?INDEX FULL SCAN DESCENDING| IDX_T | 75264 | ? ? ? | ? 169 ? (1)| 00:00:03 |
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-

Predicate Information (identified by operation id):
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;
? ?2 &#8211; filter(ROWNUM=1)
? ?6 &#8211; filter(ROWNUM=1)
Statistics
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
? ? ? ? ? 0 ?recursive calls
? ? ? ? ? 0 ?db block gets
? ? ??? ? 6 ?consistent gets
? ? ? ? ? 0 ?physical reads
? ? ? ? ? 0 ?redo size
? ? ? ?1509 ?bytes sent via SQL*Net to client
? ? ? ? 415 ?bytes received via SQL*Net from client
? ? ? ? ? 2 ?SQL*Net roundtrips to/from client
? ? ? ? ? 0 ?sorts (memory)
? ? ? ? ? 0 ?sorts (disk)
? ? ? ? ? 2 ?rows processed

&#8211;使用MIN,MAX扫描,并且子查询走索引,逻辑读11,虽然不及前2个,但是还不错,并且SQL简单
dingjun123@ORADB> SELECT * FROM t
? 2 ?WHERE t.object_id IN
? 3 ?(SELECT MIN(object_id) FROM t UNION ALL
? 4 ? SELECT MAX(object_id) FROM t);
2 rows selected.

Execution Plan
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
Plan hash value: 4243345848
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;
| Id ?| Operation ? ? ? ? ? ? ? ? ? ? ? | Name ? ? | Rows ?| Bytes | Cost (%CPU)| Time ? ? |
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;
| ? 0 | SELECT STATEMENT ? ? ? ? ? ? ? ?| ? ? ? ? ?| ? ? 2 | ? 220 | ? ? 8 ? (0)| 00:00:01 |
| ? 1 | ?NESTED LOOPS ? ? ? ? ? ? ? ? ? | ? ? ? ? ?| ? ? ? | ? ? ? | ? ? ? ? ? ?| ? ? ? ? ?|
| ? 2 | ? NESTED LOOPS ? ? ? ? ? ? ? ? ?| ? ? ? ? ?| ? ? 2 | ? 220 | ? ? 8 ? (0)| 00:00:01 |
| ? 3 | ? ?VIEW ? ? ? ? ? ? ? ? ? ? ? ? | VW_NSO_1 | ? ? 2 | ? ?26 | ? ? 4 ? (0)| 00:00:01 |
| ? 4 | ? ? HASH UNIQUE ? ? ? ? ? ? ? ? | ? ? ? ? ?| ? ? 2 | ? ?10 | ? ? 4 ?(50)| 00:00:01

推荐阅读
  • 本文详细介绍了如何使用libpq库与PostgreSQL后端建立连接。通过探讨PQconnectdb()函数的工作原理及其在实际应用中的使用方法,帮助读者理解并掌握建立高效、稳定的数据库连接的关键步骤。 ... [详细]
  • Windows服务与数据库交互问题解析
    本文探讨了在Windows 10(64位)环境下开发的Windows服务,旨在定期向本地MS SQL Server (v.11)插入记录。尽管服务已成功安装并运行,但记录并未正确插入。我们将详细分析可能的原因及解决方案。 ... [详细]
  • 数据库内核开发入门 | 搭建研发环境的初步指南
    本课程将带你从零开始,逐步掌握数据库内核开发的基础知识和实践技能,重点介绍如何搭建OceanBase的开发环境。 ... [详细]
  • 本文深入探讨 MyBatis 中动态 SQL 的使用方法,包括 if/where、trim 自定义字符串截取规则、choose 分支选择、封装查询和修改条件的 where/set 标签、批量处理的 foreach 标签以及内置参数和 bind 的用法。 ... [详细]
  • 使用C#开发SQL Server存储过程的指南
    本文介绍如何利用C#在SQL Server中创建存储过程,涵盖背景、步骤和应用场景,旨在帮助开发者更好地理解和应用这一技术。 ... [详细]
  • 本文探讨了适用于Spring Boot应用程序的Web版SQL管理工具,这些工具不仅支持H2数据库,还能够处理MySQL和Oracle等主流数据库的表结构修改。 ... [详细]
  • 本文详细介绍了如何通过多种编程语言(如PHP、JSP)实现网站与MySQL数据库的连接,包括创建数据库、表的基本操作,以及数据的读取和写入方法。 ... [详细]
  • 在当前众多持久层框架中,MyBatis(前身为iBatis)凭借其轻量级、易用性和对SQL的直接支持,成为许多开发者的首选。本文将详细探讨MyBatis的核心概念、设计理念及其优势。 ... [详细]
  • 在使用 DataGridView 时,如果在当前单元格中输入内容但光标未移开,点击保存按钮后,输入的内容可能无法保存。只有当光标离开单元格后,才能成功保存数据。本文将探讨如何通过调用 DataGridView 的内置方法解决此问题。 ... [详细]
  • 本文详细介绍了如何在 Linux 平台上安装和配置 PostgreSQL 数据库。通过访问官方资源并遵循特定的操作步骤,用户可以在不同发行版(如 Ubuntu 和 Red Hat)上顺利完成 PostgreSQL 的安装。 ... [详细]
  • 如何在PostgreSQL中查看数据表
    本文将指导您使用pgAdmin工具连接到PostgreSQL数据库,并展示如何浏览和查找其中的数据表。通过简单的步骤,您可以轻松访问所需的表结构和数据。 ... [详细]
  • 利用存储过程构建年度日历表的详细指南
    本文将介绍如何使用SQL存储过程创建一个完整的年度日历表。通过实例演示,帮助读者掌握存储过程的应用技巧,并提供详细的代码解析和执行步骤。 ... [详细]
  • 本文介绍了如何通过 Maven 依赖引入 SQLiteJDBC 和 HikariCP 包,从而在 Java 应用中高效地连接和操作 SQLite 数据库。文章提供了详细的代码示例,并解释了每个步骤的实现细节。 ... [详细]
  • 在使用SQL Server进行动态SQL查询时,如果遇到LIKE语句无法正确返回预期结果的情况,通常是因为参数传递方式不当。本文将详细探讨这一问题,并提供解决方案及相关的技术背景。 ... [详细]
  • 本文介绍如何通过创建替代插入触发器,使对视图的插入操作能够正确更新相关的基本表。涉及的表包括:飞机(Aircraft)、员工(Employee)和认证(Certification)。 ... [详细]
author-avatar
键盘上的泪g_752
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有