我在两个具有几乎相同配置的不同数据库服务器上运行相同的查询。查询正在对一张表进行全表扫描 (FTS)
SELECT COUNT (1) FROM tax_proposal_dtl WHERE tax_proposal_no = :b1 AND taxid != :b2 AND INSTR(:b3 , ',' || STATUS || ',' ) > 0 ;
在第一个 DB 上,我得到不到 3 秒的结果,磁盘读取为 0,而在第二个 DB 上,磁盘读取很高,经过的时间约为 9 秒
两个数据库上的表配置之间的唯一区别是,第一个表上的缓存 = 'Y',而第二个缓存 = 'N'。据我了解,在不使用 FTS 缓存的情况下,将使用直接路径读取。那么,为什么相同查询的性能会受到缓存/无缓存的影响(因为这是两个环境之间的唯一区别,甚至执行计划也是相同的)。
正如 Jon 所建议的那样,在对该主题进行了进一步研究之后(特别是关于 _SMALL_TABLE_THRESHOLD),我正在添加更多细节。
当前版本:Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit
第二个数据库的详细信息:
来自 DBA_SEGMENTS 的表的总块数 = 196736
第一个数据库的详细信息:
来自 DBA_SEGMENTS 的表的总块数 = 172288
两个数据库的执行计划相同,但有两个主要区别:a)第二个数据库缓存选项在表上为假(我尝试了更改表缓存但仍然对性能没有影响)
b) 在第 2 个 DB 上,因为 _STT 参数为 23920,因此根据 5*_STT 规则表将不被视为中型表,而在第 1 个 DB 上,_STT 参数为 48496,因此根据 5*_STT 规则表将被视为中型表。
下面是基于我迄今为止对 _STT 的研究的图表,它是一个 Cache 参数,用于说明系统在不同表大小下的行为方式。
请让我知道我的理解是否正确,假设缓存选项对中型或大型表没有影响,但它有助于在 LRU 中保留更长时间的小型表。因此,基于上述假设和图表,我得出的结论是,在第 2 个 DB 表的情况下,它被归类为大型表,因此 DPR 和更多经过的时间,而在第 1 个数据库表的情况下,它被归类为中型表,因此缓存读取和经过的时间更少。
根据此链接,我已在第二个 DB 的会话中设置 _STT 参数
alter session set "_small_table_threshold"=300000;
因此,性能得到了显着提高,几乎与第一个 0 磁盘读取的 DB 相同,因为这意味着表将被认为是小型的。
我在研究中使用了以下文章。
https://jonathanlewis.wordpress.com/2011/03/24/small-tables/
https://dioncho.wordpress.com/tag/full-table-scan/
https://mikesmithers.wordpress.com/2016/06/23/oracle-pinning-table-data-in-the-buffer-cache/
http://afatkulin.blogspot.com/2012/07/serial-direct-path-reads-in-11gr2-and.html
http://afatkulin.blogspot.com/2009/01/11g-adaptive-direct-path-reads-what-is.html