自动跟踪统计比较
Auto trace statistics comparison
比较生成相同行数的不同查询时,如何判断哪个 oracle 计划好?
如果我不得不认为last_consistent_gets低,我看到经过的时间更多。
对于其他查询,经过的时间更少,但 last_consistent_gets 更多。
非常混乱。
运行时间通常是 Oracle 性能最重要的指标。理论上,我们有时可能想牺牲一个 SQL 语句的 运行 时间来为其他语句保留资源。实际上,这种情况很少见。
在您的特定情况下,很多时候使用更一致获取的语句既更快又更高效。例如,当从 table 中检索大部分数据时,完整 table 扫描通常比索引扫描更有效。完整的 table 扫描可以使用 multi-block 读取,这比索引扫描的多次 single-block 读取效率更高。存储系统读取大块数据的速度通常比读取多个小块数据快得多。
下面的示例比较了从 table 读取 25% 的数据。索引方法只使用了一半的一致性获取,但它的速度也是两倍多。
示例架构
创建一个简单的 table 并编制索引并收集统计信息。
create table test1(a number, b number);
insert into test1 select level, level from dual connect by level <= 1000000;
create index test1_ids on test1(a);
begin
dbms_stats.gather_table_stats(user, 'TEST1');
end;
/
自动追踪
下面的代码显示了完整的 table 扫描消耗了 2082 次一致获取,强制索引访问消耗了 1078 次一致获取。
JHELLER@orclpdb> set autotrace on;
JHELLER@orclpdb> set linesize 120;
JHELLER@orclpdb> select sum(b) from test1 where a >= 750000;
SUM(B)
----------
2.1875E+11
Execution Plan
----------------------------------------------------------
Plan hash value: 3896847026
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 10 | 597 (3)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 10 | | |
|* 2 | TABLE ACCESS FULL| TEST1 | 250K| 2441K| 597 (3)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("A">=750000)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
2082 consistent gets
0 physical reads
0 redo size
552 bytes sent via SQL*Net to client
404 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
JHELLER@orclpdb> select /*+ index(test1) */ sum(b) from test1 where a >= 750000;
SUM(B)
----------
2.1875E+11
Execution Plan
----------------------------------------------------------
Plan hash value: 1247966541
--------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 10 | 1084 (1)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 10 | | |
| 2 | TABLE ACCESS BY INDEX ROWID BATCHED| TEST1 | 250K| 2441K| 1084 (1)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | TEST1_IDS | 250K| | 563 (1)| 00:00:01 |
--------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("A">=750000)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
1078 consistent gets
0 physical reads
0 redo size
552 bytes sent via SQL*Net to client
424 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
性能
如果你 运行 循环语句一百次(并且 运行 那些循环多次以忽略缓存和其他系统 activity),完整的 table 扫描版本 运行s 比强制索引扫描版本快得多。
--Seconds to run plan with more consistent gets: 1.7, 1.7, 1.8
declare
v_count number;
begin
for i in 1 .. 100 loop
select sum(b) into v_count from test1 where a >= 750000;
end loop;
end;
/
--Seconds to run plan with less consistent gets: 4.5, 4,5, 4.5
declare
v_count number;
begin
for i in 1 .. 100 loop
select /*+ index(test1) */ sum(b) into v_count from test1 where a >= 750000;
end loop;
end;
/
例外情况
有些时候资源消耗比流逝的时间更重要。例如,并行性是一种欺骗,因为它迫使系统更努力地工作,而不是更聪明地工作。单个 out-of-control 并行查询可以关闭整个系统。有时您需要将语句分解为效率较低的版本,以减少锁定某些内容的时间,或者避免消耗过多的 UNDO 或临时 table 空间。
但上面的例子是有些不常见的例外,它们通常只发生在处理查询大量数据的数据仓库时。对于大多数 OLTP 系统,每个查询都不到一秒,经过的时间是您唯一需要担心的指标。
比较生成相同行数的不同查询时,如何判断哪个 oracle 计划好?
如果我不得不认为last_consistent_gets低,我看到经过的时间更多。 对于其他查询,经过的时间更少,但 last_consistent_gets 更多。
非常混乱。
运行时间通常是 Oracle 性能最重要的指标。理论上,我们有时可能想牺牲一个 SQL 语句的 运行 时间来为其他语句保留资源。实际上,这种情况很少见。
在您的特定情况下,很多时候使用更一致获取的语句既更快又更高效。例如,当从 table 中检索大部分数据时,完整 table 扫描通常比索引扫描更有效。完整的 table 扫描可以使用 multi-block 读取,这比索引扫描的多次 single-block 读取效率更高。存储系统读取大块数据的速度通常比读取多个小块数据快得多。
下面的示例比较了从 table 读取 25% 的数据。索引方法只使用了一半的一致性获取,但它的速度也是两倍多。
示例架构
创建一个简单的 table 并编制索引并收集统计信息。
create table test1(a number, b number);
insert into test1 select level, level from dual connect by level <= 1000000;
create index test1_ids on test1(a);
begin
dbms_stats.gather_table_stats(user, 'TEST1');
end;
/
自动追踪
下面的代码显示了完整的 table 扫描消耗了 2082 次一致获取,强制索引访问消耗了 1078 次一致获取。
JHELLER@orclpdb> set autotrace on;
JHELLER@orclpdb> set linesize 120;
JHELLER@orclpdb> select sum(b) from test1 where a >= 750000;
SUM(B)
----------
2.1875E+11
Execution Plan
----------------------------------------------------------
Plan hash value: 3896847026
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 10 | 597 (3)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 10 | | |
|* 2 | TABLE ACCESS FULL| TEST1 | 250K| 2441K| 597 (3)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("A">=750000)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
2082 consistent gets
0 physical reads
0 redo size
552 bytes sent via SQL*Net to client
404 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
JHELLER@orclpdb> select /*+ index(test1) */ sum(b) from test1 where a >= 750000;
SUM(B)
----------
2.1875E+11
Execution Plan
----------------------------------------------------------
Plan hash value: 1247966541
--------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 10 | 1084 (1)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 10 | | |
| 2 | TABLE ACCESS BY INDEX ROWID BATCHED| TEST1 | 250K| 2441K| 1084 (1)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | TEST1_IDS | 250K| | 563 (1)| 00:00:01 |
--------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("A">=750000)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
1078 consistent gets
0 physical reads
0 redo size
552 bytes sent via SQL*Net to client
424 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
性能
如果你 运行 循环语句一百次(并且 运行 那些循环多次以忽略缓存和其他系统 activity),完整的 table 扫描版本 运行s 比强制索引扫描版本快得多。
--Seconds to run plan with more consistent gets: 1.7, 1.7, 1.8
declare
v_count number;
begin
for i in 1 .. 100 loop
select sum(b) into v_count from test1 where a >= 750000;
end loop;
end;
/
--Seconds to run plan with less consistent gets: 4.5, 4,5, 4.5
declare
v_count number;
begin
for i in 1 .. 100 loop
select /*+ index(test1) */ sum(b) into v_count from test1 where a >= 750000;
end loop;
end;
/
例外情况
有些时候资源消耗比流逝的时间更重要。例如,并行性是一种欺骗,因为它迫使系统更努力地工作,而不是更聪明地工作。单个 out-of-control 并行查询可以关闭整个系统。有时您需要将语句分解为效率较低的版本,以减少锁定某些内容的时间,或者避免消耗过多的 UNDO 或临时 table 空间。
但上面的例子是有些不常见的例外,它们通常只发生在处理查询大量数据的数据仓库时。对于大多数 OLTP 系统,每个查询都不到一秒,经过的时间是您唯一需要担心的指标。