优化06-物理读和IO
物理读和IO
在Oracle中,物理读是将磁盘中的数据块(block),读取到内存中的过程,一个块的读取就是一次物理读。物理读不等于IO数,因为Oracle中对磁盘中连续的块可以使用多块读,由db_file_multiblock_read_count 参数控制,一般不建议修改。
SQL> show parameter db_file_multi NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_file_multiblock_read_count integer 128
这里,db_file_multiblock_read_count为默认的128个数据块。
物理读效率
对于单块读,IO的响应时间就是一个物理读的响应时间,因此IO响应时间直接影响物理的的效率。
一般影响IO响应时间的有以下指标:
- 磁盘类型:机械盘和固态盘,而机械盘的转速直接影响IO读取速率,机械盘的转速由rpm表示,常见的机械盘的rpm有7500、15000。
- 磁盘接口:常见机械盘的接口有STAT、SAS等,常见的固态盘接口有PCIe、NVMe等,不同接口支持最大速度不一样。
- IO类型:单块读/多块读、顺序读/随机读。
对于机械磁盘,一次IO的响应时间一般为4ms-8ms。
单块读和多快读
#清空buffer cache 确保全部数据物理读
alter system flush buffer_cache
SQL> set autotrace traceonly;
#开启全量统计
SQL> alter session set statistics_level=all;
#查看全表扫描的统计信息
SQL> select * from tab2;Execution Plan
----------------------------------------------------------
Plan hash value: 2156729920--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 72729 | 9446K| 396 (1)| 00:00:01 |
| 1 | TABLE ACCESS FULL| TAB2 | 72729 | 9446K| 396 (1)| 00:00:01 |
--------------------------------------------------------------------------Statistics
----------------------------------------------------------131 recursive calls1 db block gets1578773 consistent gets361722 physical reads184 redo size1278647716 bytes sent via SQL*Net to client13654258 bytes received via SQL*Net from client1241243 SQL*Net roundtrips to/from client10 sorts (memory)0 sorts (disk)18618624 rows processed#再次清空buffer cachealter system flush buffer_cache;#查看索引扫描的统计信息select /*+ index(t2,idx_objid) */ * from tab2 t2 where object_id>0;Execution Plan
----------------------------------------------------------
Plan hash value: 2653761239-------------------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |-------------------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 72728 | 9446K| 9331K(1)| 00:06:05 || 1 | TABLE ACCESS BY INDEX ROWID BATCHED| TAB2 | 72728 | 9446K| 9331K (1)| 00:06:05 ||* 2 | INDEX RANGE SCAN | IDX_OBJID | 9309K| | 20641 (1)| 00:00:01 |-------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------2 - access("OBJECT_ID">0)Statistics
----------------------------------------------------------1 recursive calls0 db block gets19863223 consistent gets402506 physical reads0 redo size394392655 bytes sent via SQL*Net to client13654071 bytes received via SQL*Net from client1241226 SQL*Net roundtrips to/from client0 sorts (memory)0 sorts (disk)18618368 rows processed#通过查询v$sql 确定两个SQL的SQL_ID 为fvu2sdrakwgfn和4kxudxqvgn7q7#查看逻辑读和IO次数SQL> select sql_id,disk_reads,direct_reads,physical_read_requests from v$sqlstats where sql_id in('fvu2sdrakwgfn','4kxudxqvgn7q7');SQL_ID DISK_READS DIRECT_READS PHYSICAL_READ_REQUESTS
------------- ---------- ------------ ----------------------
4kxudxqvgn7q7 402506 0 402506
fvu2sdrakwgfn 361722 361528 3045#DISK_READS:物理读
#DIRECT_READS:直接路径读
#PHYSICAL_READ_REQUESTS:物理请求次数,也就是IO次数由此可以发现单块读一般是索引扫描,而多块读是全表扫描。
思考:为什么通过IOSTAT查看磁盘IO只有4MB/s,但是磁盘就已经100% busy(util%)了呢?
如果当前IO多为单块读8K,要读取4M数据,IOPS为(4192/8K)=500,而一般机械磁盘最大IOPS只能达到250左右,所以磁盘很繁忙,积压下来会100% busy;
如果当前IO对多块读,最大一次IO可达128*8k=1M,读取4M数据IOPS为4,所以磁盘会很空闲。