当前位置: 首页 > 科技观察

你知道Oracle逻辑读和物理读吗?

时间:2023-03-14 16:21:10 科技观察

1。物理读(physicalread)物理读是从磁盘读数据到缓冲区的过程。通常,如果需要数据,发现buffer中不存在catch,也就是oracle会进行一次物理读。当数据块第一次被读取时,会缓存在buffercache中,当数据块被第二次读取和修改时,会在内存buffercache中。下面是一个例子:1.1首先阅读:C:\DocumentsandSettings\PaulYi>sqlplus"/assysdba"SQL*Plus:Release9.2.0.4.0-ProductiononThuFeb2809:32:042008Copyright(c)1982年、2002年,甲骨文公司。保留所有权利。连接到:Oracle9i企业版9.2.0.4.0版-ProductionWithPartitioning、OLAP和OracleDataMining选项JServer9.2.0.4.0版-ProductionSQL>setautotracetraceonlySQL>select*fromtest;ExecutionPlan-------------------------------------------------------0SELECTSTATEMENToptimizer=CHOOSE(Cost=2Card=4Bytes=8)10TABLEACCESS(FULL)OF'TEST'(Cost=2Card=4Bytes=8)Statistics-----------------------------------------------------175次递归调用0dbblockgets24consistentgets9physicalreads--9physicalreads0redosize373bytessendviaSQL*Nettoclient503bytesreceivedviaSQL*Netfromclient2SQL*Netroundtripsto/fromclient2排序(内存)0排序(磁盘)1行处理1.2秒读取SQL>select*fromtest;ExecutionPlan---------------------------------------------------------0SELECTSTATEMENToptimizer=CHOOSE(Cost=2Card=4Bytes=8)10表访问(完全)“测试”(成本=2卡=4字节=8)统计---------------------------------------------------------0递归调用0db块gets7consistentgets0physicalreads--nophysicalhappeningReadit,直接从缓冲区缓存读取0重做大小373字节通过SQL*Net发送到客户端503字节通过SQL*Net从客户端接收2SQL*Net往返客户端0排序(内存)0排序(磁盘)1行处理1.3数据块是重新读入缓冲区缓存。如果有新的数据要读入BufferCache,而BufferCache没有足够的空闲空间,Oracle会使用LRU算法将数据存储在LRU链表的LRU端。替换后,再次访问数据时,需要重新从磁盘读取。SQL>altersessionsetevents'immediatetracenameflush_cache';--cleardatabufferSessionaltered.SQL>select*fromtest;ExecutionPlan------------------------------------------------------------0SELECTSTATEMENToptimizer=CHOOSE(Cost=2Card=4Bytes=8)10TABLEACCESS(FULL)OF'TEST'(Cost=2Card=4Bytes=8)统计--------------------------------------------------------0递归调用0db块gets7一致gets6物理读取--andPhysicalread0redosize373bytessentviaSQL*Nettoclient503bytes通过SQL*Net从client2接收SQL*Net往返client0排序(内存)0排序(磁盘)1行处理2。逻辑读(bufferread)逻辑读是指从(或查看)BufferCache中读取数据块。根据访问数据块的方式不同,可以分为立即读(CurrentRead)和一致读(ConsistentRead)。注意:逻辑IO只有逻辑读,没有逻辑写。InstantreadInstantread就是读取数据块的当前***数据。BufferCache中任何时候都只有一份当前数据块的副本。立即读取通常发生在修改或删除数据时。这时,进程会对数据加行级锁,将数据标记为“脏”数据。SQL>select*fromtestforupdate;ExecutionPlan----------------------------------------------------------0SELECTSTATEMENToptimizer=CHOOSE(Cost=2Card=4Bytes=8)10FORUPDATE21TABLEACCESS(FULL)OF'TEST'(Cost=2Card=4Bytes=8)Statistics--------------------------------------------------------0递归调用1db块获取14一致获取0物理读取252重做大小386字节通过SQL*Net发送到客户端503字节通过SQL*Net从客户端2SQL*Net接收往返客户端0排序(内存)0排序(磁盘)1行processedSQL>consistentreadOracle是一个多用户系统。当一个session开始读取数据还没有读完时,其他session可能会修改它要读取的数据。如果session读取修改后的数据,会造成数据不一致。一致性读取是为了保证数据的一致性。在BufferCache中的数据块上,会有最后一次修改数据块时的SCN。如果一个事务需要修改数据块中的数据,它会先在回滚段中保存一个数据块,其中包含修改前的数据和SCN,然后在BufferCache中更新数据和该数据块的SCN,并将其标记为“脏”数据。当其他进程读取一个数据块时,首先将数据块上的SCN与自己的SCN进行比较,如果数据块上的SCN小于等于本进程的SCN本身,会直接读取数据块上的数据;如果数据块上的SCN大于进程本身的SCN,则会从回滚段fetch数据中读取修改前的数据块。通常,普通查询是一致的阅读。下面的例子帮助你理解一致性阅读:在会话1中:SQL>select*fromtest;ID----------1000SQL>updatetestsetid=2000;1rowupdated。在会话2中:SQL>setautotraceonSQL>select*fromtest;ID------------1000ExecutionPlan-----------------------------------------------------0SELECTSTATEMENToptimizer=CHOOSE(Cost=2Card=4Bytes=8)10表访问(完全)“测试”(成本=2卡=4字节=8)统计信息---------------------------------------------------------0递归调用0db块获取9一致获取当没有更新时7一致获取,更多解释2consistentgets这些2将从回滚段获得0物理读取52重做size373字节通过SQL*Net发送到client503字节通过SQL*Net从客户端接收2SQL*Net往返客户端0排序(内存)0排序(磁盘)1行已处理SQL>