• 优化高手都需要深入的访问路径(ACCESS PATH)


    访问路径:通过哪种方式对数据进行访问. 全表扫描、索引扫描或ROWID获取数据。

    常见访问路径

    1.TABLE ACCESS FULL(全表扫描)

    • 多块读
    • HINT:FULL(表名/别名)
    • 等待事件为db file scattered read.
    • 若为并行全表扫描,等待事件为direct path read.

    2.TABLE ACCESS BY USER ROWID

    • 直接用ROWID获取数据,单块读。
    • 该访问路径在Oracle所有的访问路径中性能是最好的

    3.TABLE ACCESS BY ROWID RANGE

    • 表示ROWID 范围扫描,多块读。
    • 因为同一个块里面的ROWID是连续的,同一个EXTENT里面的ROWID也是连续的,所以可以多块读。

    4.TABLE ACCESS BY INDEX ROWID

    • 回表,单块读

    5.INDEX UNIQUE SCAN

    • 索引唯一扫描,单块读。
    • 对唯一索引或者主键列进行等值查询,就会走INDEX UNIQUE SCAN
    • 其性能仅次于TABLE ACCESS BY USER ROWID
    1. scott@orclpdb1:orclcdb> set autot trace
    2. scott@orclpdb1:orclcdb>
    3. scott@orclpdb1:orclcdb>
    4. scott@orclpdb1:orclcdb> select * from emp where empno=7369;
    5. 1 row selected.
    6. Execution Plan
    7. ----------------------------------------------------------
    8. Plan hash value: 2949544139
    9. --------------------------------------------------------------------------------------
    10. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    11. --------------------------------------------------------------------------------------
    12. | 0 | SELECT STATEMENT | | 1 | 38 | 1 (0)| 00:00:01 |
    13. | 1 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 38 | 1 (0)| 00:00:01 |
    14. |* 2 | INDEX UNIQUE SCAN | PK_EMP | 1 | | 0 (0)| 00:00:01 |
    15. --------------------------------------------------------------------------------------
    16. Predicate Information (identified by operation id):
    17. ---------------------------------------------------
    18. 2 - access("EMPNO"=7369)
    19. Statistics
    20. ----------------------------------------------------------
    21. 0 recursive calls
    22. 0 db block gets
    23. 2 consistent gets
    24. 0 physical reads
    25. 0 redo size
    26. 961 bytes sent via SQL*Net to client
    27. 385 bytes received via SQL*Net from client
    28. 1 SQL*Net roundtrips to/from client
    29. 0 sorts (memory)
    30. 0 sorts (disk)
    31. 1 rows processed
    32. scott@orclpdb1:orclcdb>

    6.INDEX RANGE SCAN

    • 索引范围扫描,单块读,返回的数据是有序的,
    • HINT:INDEX(表名/别名 索引名)
    • 对唯一索引或者主键索引进行范围查找(INDEX RANGE SCAN,等待事件db file sequential read)。对非唯一索引进行等值查找.
    1. scott@orclpdb1:orclcdb> select * from test where object_id=100;
    2. 1 row selected.
    3. Execution Plan
    4. ----------------------------------------------------------
    5. Plan hash value: 3297604684
    6. ----------------------------------------------------------------------------------------------
    7. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    8. ----------------------------------------------------------------------------------------------
    9. | 0 | SELECT STATEMENT | | 1 | 132 | 2 (0)| 00:00:01 |
    10. | 1 | TABLE ACCESS BY INDEX ROWID BATCHED| TEST | 1 | 132 | 2 (0)| 00:00:01 |
    11. |* 2 | INDEX RANGE SCAN | IDX_ID | 1 | | 1 (0)| 00:00:01 |
    12. ----------------------------------------------------------------------------------------------
    13. Predicate Information (identified by operation id):
    14. ---------------------------------------------------
    15. 2 - access("OBJECT_ID"=100)
    16. Statistics
    17. ----------------------------------------------------------
    18. 136 recursive calls
    19. 0 db block gets
    20. 408 consistent gets
    21. 33 physical reads
    22. 0 redo size
    23. 2686 bytes sent via SQL*Net to client
    24. 621 bytes received via SQL*Net from client
    25. 2 SQL*Net roundtrips to/from client
    26. 74 sorts (memory)
    27. 0 sorts (disk)
    28. 1 rows processed
    29. scott@orclpdb1:orclcdb>

    索引范围扫描默认是从索引中最左边的叶子块开始,然后往右边的叶子块扫描(从小到大),当检查到不匹配数据的时候,就停止扫描。

    1. scott@orclpdb1:orclcdb> select * from test where object_id<100 order by object_id desc;
    2. 98 rows selected.
    3. Execution Plan
    4. ----------------------------------------------------------
    5. Plan hash value: 1069979465
    6. ---------------------------------------------------------------------------------------
    7. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    8. ---------------------------------------------------------------------------------------
    9. | 0 | SELECT STATEMENT | | 94 | 12408 | 5 (0)| 00:00:01 |
    10. | 1 | TABLE ACCESS BY INDEX ROWID | TEST | 94 | 12408 | 5 (0)| 00:00:01 |
    11. |* 2 | INDEX RANGE SCAN DESCENDING| IDX_ID | 94 | | 2 (0)| 00:00:01 |
    12. ---------------------------------------------------------------------------------------
    13. Predicate Information (identified by operation id):
    14. ---------------------------------------------------
    15. 2 - access("OBJECT_ID"<100)
    16. Statistics
    17. ----------------------------------------------------------
    18. 1 recursive calls
    19. 0 db block gets
    20. 18 consistent gets
    21. 1 physical reads
    22. 0 redo size
    23. 14379 bytes sent via SQL*Net to client
    24. 711 bytes received via SQL*Net from client
    25. 8 SQL*Net roundtrips to/from client
    26. 0 sorts (memory)
    27. 0 sorts (disk)
    28. 98 rows processed
    29. scott@orclpdb1:orclcdb>

      INDEX RANGE SCAN DESCENDING 表示索引降序范围扫描,从右往左扫描,返回的数据是降序显示的。

    7.INDEX SKIP SCAN

    • 索引跳跃扫描,单块读。
    • 返回的数据是有序的
    • HINT:INDEX_SS(表名/别名 索引名)
    • 当组合索引的引导列(第一个列)没有在where条件中,并且组合索引的引导列/前几个列的基数很低,where过滤条件对组合索引中非引导列进行过滤的时候就会发生索引跳跃扫描。
    • 等待事件为 db file sequential read.
    1. scott@orclpdb1:orclcdb> create index idx_ownerid on test(owner,object_id);
    2. Index created.
    3. scott@orclpdb1:orclcdb> drop index idx_id;
    4. Index dropped.
    5. scott@orclpdb1:orclcdb> select * from test where object_id<100;
    6. 98 rows selected.
    7. Execution Plan
    8. ----------------------------------------------------------
    9. Plan hash value: 607061290
    10. ---------------------------------------------------------------------------------------------------
    11. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    12. ---------------------------------------------------------------------------------------------------
    13. | 0 | SELECT STATEMENT | | 94 | 12408 | 42 (0)| 00:00:01 |
    14. | 1 | TABLE ACCESS BY INDEX ROWID BATCHED| TEST | 94 | 12408 | 42 (0)| 00:00:01 |
    15. |* 2 | INDEX SKIP SCAN | IDX_OWNERID | 94 | | 39 (0)| 00:00:01 |
    16. ---------------------------------------------------------------------------------------------------
    17. Predicate Information (identified by operation id):
    18. ---------------------------------------------------
    19. 2 - access("OBJECT_ID"<100)
    20. filter("OBJECT_ID"<100)
    21. Statistics
    22. ----------------------------------------------------------
    23. 59 recursive calls
    24. 0 db block gets
    25. 92 consistent gets
    26. 17 physical reads
    27. 0 redo size
    28. 14379 bytes sent via SQL*Net to client
    29. 466 bytes received via SQL*Net from client
    30. 8 SQL*Net roundtrips to/from client
    31. 6 sorts (memory)
    32. 0 sorts (disk)
    33. 98 rows processed
    34. scott@orclpdb1:orclcdb>

    8.INDEX FULL SCAN

    • INDEX FULL SCAN 表示索引全扫描,单块读,返回的数据是有序的。
    • HINT:INDEX(表名/别名 索引名)
    • 索引全扫描会扫描索引中所有的叶子块(从左往右扫描)
    • 若索引很大,会产生严重的性能问题(因为是单块读)
    • 等待事件: db file sequential read
    1. scott@orclpdb1:orclcdb> select * from test order by object_id,owner;
    2. 73516 rows selected.
    3. Execution Plan
    4. ----------------------------------------------------------
    5. Plan hash value: 2007178810
    6. -----------------------------------------------------------------------------------
    7. | Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
    8. -----------------------------------------------------------------------------------
    9. | 0 | SELECT STATEMENT | | 73516 | 9476K| | 2570 (1)| 00:00:01 |
    10. | 1 | SORT ORDER BY | | 73516 | 9476K| 13M| 2570 (1)| 00:00:01 |
    11. | 2 | TABLE ACCESS FULL| TEST | 73516 | 9476K| | 399 (1)| 00:00:01 |
    12. -----------------------------------------------------------------------------------
    13. Statistics
    14. ----------------------------------------------------------
    15. 1 recursive calls
    16. 0 db block gets
    17. 1430 consistent gets
    18. 0 physical reads
    19. 0 redo size
    20. 4868592 bytes sent via SQL*Net to client
    21. 54537 bytes received via SQL*Net from client
    22. 4903 SQL*Net roundtrips to/from client
    23. 1 sorts (memory)
    24. 0 sorts (disk)
    25. 73516 rows processed
    26. scott@orclpdb1:orclcdb> create index idx_idowner on test(object_id,owner,0);
    27. Index created.
    28. scott@orclpdb1:orclcdb> select * from test order by object_id,owner;
    29. 73516 rows selected.
    30. Execution Plan
    31. ----------------------------------------------------------
    32. Plan hash value: 3870803568
    33. -------------------------------------------------------------------------------------------
    34. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    35. -------------------------------------------------------------------------------------------
    36. | 0 | SELECT STATEMENT | | 73516 | 9476K| 1865 (1)| 00:00:01 |
    37. | 1 | TABLE ACCESS BY INDEX ROWID| TEST | 73516 | 9476K| 1865 (1)| 00:00:01 |
    38. | 2 | INDEX FULL SCAN | IDX_IDOWNER | 73516 | | 234 (1)| 00:00:01 |
    39. -------------------------------------------------------------------------------------------
    40. Statistics
    41. ----------------------------------------------------------
    42. 1 recursive calls
    43. 0 db block gets
    44. 11531 consistent gets
    45. 232 physical reads
    46. 0 redo size
    47. 4868592 bytes sent via SQL*Net to client
    48. 54316 bytes received via SQL*Net from client
    49. 4903 SQL*Net roundtrips to/from client
    50. 0 sorts (memory)
    51. 0 sorts (disk)
    52. 73516 rows processed
    53. scott@orclpdb1:orclcdb>

    9.INDEX FAST FULL SCAN

    • 索引快速全扫描,多块读。
    • HINT:INDEX_FFS(表名/别名 索引名)
    • 等待事件 db file scattered read
    1. scott@orclpdb1:orclcdb> drop index idx_ownername;
    2. Index dropped.
    3. scott@orclpdb1:orclcdb> create index idx_ownername on test(owner,object_name,0);
    4. Index created.
    5. scott@orclpdb1:orclcdb> select owner,object_name from test;
    6. 73516 rows selected.
    7. Execution Plan
    8. ----------------------------------------------------------
    9. Plan hash value: 3888663772
    10. --------------------------------------------------------------------------------------
    11. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    12. --------------------------------------------------------------------------------------
    13. | 0 | SELECT STATEMENT | | 73516 | 2871K| 146 (0)| 00:00:01 |
    14. | 1 | INDEX FAST FULL SCAN| IDX_OWNERNAME | 73516 | 2871K| 146 (0)| 00:00:01 |
    15. --------------------------------------------------------------------------------------
    16. Statistics
    17. ----------------------------------------------------------
    18. 1 recursive calls
    19. 0 db block gets
    20. 5405 consistent gets
    21. 537 physical reads
    22. 0 redo size
    23. 3773365 bytes sent via SQL*Net to client
    24. 54307 bytes received via SQL*Net from client
    25. 4903 SQL*Net roundtrips to/from client
    26. 0 sorts (memory)
    27. 0 sorts (disk)
    28. 73516 rows processed
    29. scott@orclpdb1:orclcdb> create index idx_id on test(object_id);
    30. Index created.
    31. scott@orclpdb1:orclcdb> select object_name from test where object_id<100;
    32. 98 rows selected.
    33. Execution Plan
    34. ----------------------------------------------------------
    35. Plan hash value: 3297604684
    36. ----------------------------------------------------------------------------------------------
    37. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    38. ----------------------------------------------------------------------------------------------
    39. | 0 | SELECT STATEMENT | | 94 | 3760 | 5 (0)| 00:00:01 |
    40. | 1 | TABLE ACCESS BY INDEX ROWID BATCHED| TEST | 94 | 3760 | 5 (0)| 00:00:01 |
    41. |* 2 | INDEX RANGE SCAN | IDX_ID | 94 | | 2 (0)| 00:00:01 |
    42. ----------------------------------------------------------------------------------------------
    43. Predicate Information (identified by operation id):
    44. ---------------------------------------------------
    45. 2 - access("OBJECT_ID"<100)
    46. Statistics
    47. ----------------------------------------------------------
    48. 1 recursive calls
    49. 0 db block gets
    50. 18 consistent gets
    51. 1 physical reads
    52. 0 redo size
    53. 2851 bytes sent via SQL*Net to client
    54. 476 bytes received via SQL*Net from client
    55. 8 SQL*Net roundtrips to/from client
    56. 0 sorts (memory)
    57. 0 sorts (disk)
    58. 98 rows processed
    59. scott@orclpdb1:orclcdb> create index idx_idname on test(object_id,object_name);
    60. Index created.
    61. scott@orclpdb1:orclcdb> select object_name from test where object_id<100;
    62. 98 rows selected.
    63. Execution Plan
    64. ----------------------------------------------------------
    65. Plan hash value: 3678957952
    66. -------------------------------------------------------------------------------
    67. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    68. -------------------------------------------------------------------------------
    69. | 0 | SELECT STATEMENT | | 94 | 3760 | 2 (0)| 00:00:01 |
    70. |* 1 | INDEX RANGE SCAN| IDX_IDNAME | 94 | 3760 | 2 (0)| 00:00:01 |
    71. -------------------------------------------------------------------------------
    72. Predicate Information (identified by operation id):
    73. ---------------------------------------------------
    74. 1 - access("OBJECT_ID"<100)
    75. Statistics
    76. ----------------------------------------------------------
    77. 1 recursive calls
    78. 0 db block gets
    79. 9 consistent gets
    80. 1 physical reads
    81. 0 redo size
    82. 2851 bytes sent via SQL*Net to client
    83. 476 bytes received via SQL*Net from client
    84. 8 SQL*Net roundtrips to/from client
    85. 0 sorts (memory)
    86. 0 sorts (disk)
    87. 98 rows processed
    88. scott@orclpdb1:orclcdb> select object_name from test where object_id>100;
    89. 73415 rows selected.
    90. Execution Plan
    91. ----------------------------------------------------------
    92. Plan hash value: 252646278
    93. -----------------------------------------------------------------------------------
    94. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    95. -----------------------------------------------------------------------------------
    96. | 0 | SELECT STATEMENT | | 73420 | 2867K| 142 (1)| 00:00:01 |
    97. |* 1 | INDEX FAST FULL SCAN| IDX_IDNAME | 73420 | 2867K| 142 (1)| 00:00:01 |
    98. -----------------------------------------------------------------------------------
    99. Predicate Information (identified by operation id):
    100. ---------------------------------------------------
    101. 1 - filter("OBJECT_ID">100)
    102. Statistics
    103. ----------------------------------------------------------
    104. 1 recursive calls
    105. 0 db block gets
    106. 5386 consistent gets
    107. 513 physical reads
    108. 0 redo size
    109. 3530801 bytes sent via SQL*Net to client
    110. 54686 bytes received via SQL*Net from client
    111. 4896 SQL*Net roundtrips to/from client
    112. 0 sorts (memory)
    113. 0 sorts (disk)
    114. 73415 rows processed
    115. scott@orclpdb1:orclcdb>

    10.INDEX FULL SCAN(MIN/MAX)

    • 索引最小、最大值扫描、单块读
    • INDEX FULL SCAN(MIN/MAX) 只会访问“索引高度”个索引块,其性能与INDEX UNIQUE SCAN一样,其性能仅次于TABLE ACCESS BY USER ROWID

    11.MAT_VIEW REWRITE ACCESS FULL

    • MAT_VIEW REWRITE ACCESS FULL 表示物化视图全表扫描、多块读。
    • 因为物化视图本质上也是一个表,所以其扫描方式与全表扫描一样。
    1. scott@orclpdb1:orclcdb>
    2. scott@orclpdb1:orclcdb>
    3. scott@orclpdb1:orclcdb> create materialized view test_mv build immediate enable query rewrite
    4. 2 as select object_id,object_name from test;
    5. Materialized view created.
    6. scott@orclpdb1:orclcdb> select object_id,object_name from test;
    7. 73516 rows selected.
    8. Execution Plan
    9. ----------------------------------------------------------
    10. Plan hash value: 1627509066
    11. ----------------------------------------------------------------------------------------
    12. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    13. ----------------------------------------------------------------------------------------
    14. | 0 | SELECT STATEMENT | | 73516 | 2799K| 129 (1)| 00:00:01 |
    15. | 1 | MAT_VIEW REWRITE ACCESS FULL| TEST_MV | 73516 | 2799K| 129 (1)| 00:00:01 |
    16. ----------------------------------------------------------------------------------------
    17. Statistics
    18. ----------------------------------------------------------
    19. 36 recursive calls
    20. 12 db block gets
    21. 5370 consistent gets
    22. 453 physical reads
    23. 1980 redo size
    24. 4184006 bytes sent via SQL*Net to client
    25. 54311 bytes received via SQL*Net from client
    26. 4903 SQL*Net roundtrips to/from client
    27. 2 sorts (memory)
    28. 0 sorts (disk)
    29. 73516 rows processed
    30. scott@orclpdb1:orclcdb>

    因为物化视图TEST_MV 已经包含查询需要的字段,所以该SQL会直接访问物化视图TEST_MV.

    2单块单读与多块读

    • 单块读:从磁盘1次读取1个块到buffer cache.
    • 多块读:从磁盘1次读取多个块到buffer cache.
    • 如果数据块都已经缓存在buffer cache中,那就不需要物理I/O了,没有物理I/O也就不存在单块读与多块读。
    • 绝大数的平台,一次I/O最多只能读取或者写入1MB数据。
    • Oracle的块大小默认是8K,那么一次I/O最多只能写入128个块到磁盘,最多只能读取128个块到buffer cache.
    • 在判断哪个访问路径性能好的时候,通常是估算每次访问的I/O次数,谁的I/O次数少,谁的性能就好。在估算I/O次数的时候,我们只需要算个大概即可。
  • 相关阅读:
    Python | R | MATLAB群体消息和遗传病筛选多元统计模型
    前端面试题记录——vue
    网心云容器魔方在iStoreOS下的多开
    嵌入Circle映射和逐维小孔成像反向学习的鲸鱼优化算法-附代码
    将docker打包成镜像并保存到本地
    感染了后缀为.360勒索病毒如何应对?数据能够恢复吗?
    Zabbix监控部署项目
    Web安全—Web漏扫工具NetSparker安装与使用
    MongoDB基本操作增删改查
    ethers-rs rust 创建钱包,签名消息,验证签名,恢复签名地址,签名RSV对象
  • 原文地址:https://blog.csdn.net/u011868279/article/details/127414126