识别次优访问路径 2

2023年 12月 22日 81.9k 0

1.1.1      误区

检查逻辑读数时,必须注意两个会曲解指标的误区。第一个与一致读有关,第二个与行预取有关。

 

1.一致读

对于每一条SQL语句,数据库引擎都会保证处理数据的一致性。为了达到这个目的,数据块的一致性副本会基于当前数据块和回滚块在运行时创建。要执行这样的操作需要完成数个逻辑读。因此,访问路径操作执行的逻辑读数非常依赖于需要重建的块数。

 

以下代码引用自read_consistency.sql脚本生成的输出。请注意使用的查询与上节相同。根据执行统计信息,会返回相同的行数(实际上返回相同的数据)。然而,它会执行更多的逻辑读(相比28,一共执行了354)。会造成这个影响是因为修改了数据块的另一个会话需要执行该查询。由于在查询开始时修改并未提交,数据库引擎就必须重建这些块。这会导致更高的逻辑读:

select * FROM t WHERE n1 BETWEEN 6000 AND
7000 AND n2 = 19;

 

2.行预取

从优化的角度来看,应该避免基于行的处理。例如,当客户端从数据库取回数据时,它可以逐行取回,或者更好些,一次取回多行。这个技术,被称为行预取(row prefetching)。现在,让我们只看它对逻辑读数的影响。

 

简单地说,每当数据库引擎访问一个块,逻辑读就会计数一次。针对全表扫描,会有两个极端。如果将行预取设置为1,返回每行大约一个逻辑读。如果将行预取设置为大于每个表块中存储的行数,那么逻辑读就接近表的块数。以下代码引用自row_prefetching.sql脚本生成的输出。在第一个执行中,行预取设置为2,逻辑读数(5388)大约是行数(10000)的一半。在第二个执行中,由于行预取数(100)高于每个块的平均行数(25),逻辑读数(488)大约等于块数(401):

select num_rows,blocks,round(num_rows/blocks)
AS rows_per_block

FROM user_tables

WHERE table_name='T';

 

Set arraysize 2

select * FROM t;

 

注意 在SQL*Plus中,通过arraysize系统变量管理行预取数。默认值是15。

 

考虑到行预取对逻辑读数的依赖,每当出于测试目的使用诸如SQL*Plus之类的工具执行SQL语句时,都应该仔细将行预取值设置得与应用一致。换句话说,用来测试的工具预取的行数应与应用一致。如果不这样做,会导致很多错误的结果。

 

当执行的操作被阻塞时(例如,聚合操作),SQL引擎会在内部使用行预取。结果,当聚合是执行计划的一部分时,访问路径的逻辑读数会非常接近块数。换句话说,无论行预取设置成什么,每次SQL引擎访问一个块,它都会包含所有行。下面举例说明:

set arraysize 2

select sum(n1) FROM t;

相关文章

Oracle如何使用授予和撤销权限的语法和示例
Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
社区版oceanbase安装
Oracle 导出CSV工具-sqluldr2
ETL数据集成丨快速将MySQL数据迁移至Doris数据库

发布评论