SQL> create table test_max_oracle(id integer); Table created SQL> begin 2for i in1..5000000loop 3 insert into test_max_oracle (id) values (i); 4endloop; 5 commit; 6end; 7 / PL/SQL proceduresuccessfullycompleted
2.2 创建索引并表分析
1 2 3 4 5
SQL> create index idx_test_max_id on test_max_oracle (id); Index created SQL> execute dbms_stats.gather_table_stats(ownname=>'skytf',tabname=>'test_max_oracle',cascade=> true); PL/SQL proceduresuccessfullycompleted
2.3 执行时间
1 2 3 4 5 6 7 8 9 10 11 12 13
SQL> set timi on; SQL> select max(id) from test_max_oracle; MAX(ID) ---------- 5000000 Executed in 0.031 seconds
15:34:24 SKYTF@skytf> select max(id) from test_max_oracle; MAX(ID) ---------- 5000000 已用时间: 00: 00: 00.01 执行计划 ---------------------------------------------------------- Plan hash value: 1160081309 ---------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 5 | 1705 (3)| 00:00:21 | | 1 | SORT AGGREGATE | | 1 | 5 | | | | 2 | INDEX FULL SCAN(MIN/MAX)| IDX_TEST_MAX_ID | 5000K| 23M| | | ---------------------------------------------------------------------------------------------- 统计信息 ---------------------------------------------------------- 0 recursive calls 0 db block gets 3 consistent gets 0 physical reads 0 redo size 407 bytes sent via SQL*Net to client 385 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed
备注:走的是 INDEX FULL SCAN,全索引扫描会根据索引的顺序访问所有的索引 block, 这种扫描方式类似全表扫,效率不高。下面引用这段描述:
2.5 关于 INDEX FULL SCAN
In a full index scan, the database reads the entire index in order. A full index scan is available if a predicate (WHERE clause) in the SQL statement references a column in the index, and in some circumstances when no predicate is specified. A full scan can eliminate sorting because the data is ordered by index key.
francs=> select max(id) from test_max_pg; max --------- 5000000 (1 row) Time: 13.960 ms francs=> select max(id) from test_max_pg; max --------- 5000000 (1 row) Time: 2.493 ms francs=> select max(id) from test_max_pg; max --------- 5000000 (1 row) Time: 1.233 ms
francs=> explain select max(id) from test_max_pg; QUERY PLAN -------------------------------------------------------------------------------------------------------------------------- Result (cost=0.03..0.04 rows=1 width=0) InitPlan 1 (returns $0) -> Limit (cost=0.00..0.03 rows=1 width=4) -> Index Only Scan Backwardusing idx_test_max_id on test_max_pg (cost=0.00..151011.64 rows=5000000 width=4) Index Cond: (id IS NOTNULL) (5 rows)
备注:这里走的是 Index Only Scan Backward,由于索引是顺序排序的,这种扫描方式直接后向读取索引项,而不需要扫描整个索引 page,因此效率比”INDEX FULL SCAN “要高些。
四 补充
这里的测试版本: Oracle 10.2.0.1 ; PostgreSQL 9.2。
Oracle 的索引扫描方式很多,例如 index rang scan,index unique scan,index fast full scan等,比 PostgreSQL 的索引访问方式多些,这里不再描述。