暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle优化器成本的估算(10053 Trace中基于CPU成本模型的内容解析)

550

编者按:

本文作者系Walt,关注SQL开发,Oracle、MySQL、PostgreSQL、TiDB等数据库,AWS、Azure、OCI等公有云计算架构和技术。

个人主页: https://blog.csdn.net/lukeUnique。

SQL专栏课程:https://www.modb.pro/course/125

【免责声明】本公众号文章仅代表个人观点,与任何公司无关。

编辑|SQL和数据库技术(ID:SQLplusDB)


单表访问路径的评估

    Access path analysis for EMP1
    ***************************************
    SINGLE TABLE ACCESS PATH
    Single Table Cardinality Estimation for EMP1[E]
    SPD: Return code in qosdDSDirSetup: NOCTX, estType = TABLE


    kkecdn: Single Table Predicate:"E"."EMPNO">90000
    Column (#1): EMPNO(NUMBER)
    AvgLen: 5 NDV: 101395 Nulls: 0 Density: 0.000010 Min: 0.000000 Max: 4.000000
    Estimated selectivity: 0.099995 , col: #1
    Table: EMP1 Alias: E
    Card: Original: 101948.000000 Rounded: 10194 Computed: 10194.290235 Non Adjusted: 10194.290235
    Scan IO Cost (Disk) = 238.000000
    Scan CPU Cost (Disk) = 22943498.560000
    Cost of predicates:
    io = NOCOST, cpu = 50.000000, sel = 0.099995 flag = 2048 ("E"."EMPNO">90000)
    Total Scan IO Cost = 238.000000 (scan (Disk))
    + 0.000000 (io filter eval) (= 0.000000 (per row) * 101948.000000 (#rows))
    = 238.000000
    Total Scan CPU Cost = 22943498.560000 (scan (Disk))
    + 5097400.000000 (cpu filter eval) (= 50.000000 (per row) * 101948.000000 (#rows))
    = 28040898.560000
    Access Path: TableScan
    Cost: 240.132964 Resp: 240.132964 Degree: 0
    Cost_io: 238.000000 Cost_cpu: 28040899
    Resp_io: 238.000000 Resp_cpu: 28040899
    Best:: AccessPath: TableScan
    Cost: 240.132964 Degree: 1 Resp: 240.132964 Card: 10194.290235 Bytes: 0.000000


    上面的内容是10053 Trace中对于单表访问路径的评估。


    优化器成本的估算(基于CPU成本模型)


    对于优化器成本的估算是一个复杂的过程,涉及到大量的的理论和内部操作。

    Oracle对于成本的预估模型,也可以分为两种:


      CPU成本模型 :参考系统统计信息进行成本估算。
      I/O成本模型 :仅通过I/O的次数进行成本估算。


      成本模型的选择通过_optimizer_cost_model隐含参数控制。


        SQL> select a.ksppinm "PARAMETER",b.ksppstvl "VALUE",a.KSPPDESC "DESCRIPTION"
        2 from x$ksppi a, x$ksppcv b
        3 where a.indx = b.indx and
        4 a.ksppinm like '%_optimizer_cost_model%';




        PARAMETER VALUE DESCRIPTION
        -------------------------------------------------- ---------- --------------------------------------------------
        _optimizer_cost_model CHOOSE optimizer cost model

        _optimizer_cost_model隐含参数的值主要由如下三个值,成本模型的选择会根据其值相应调整。

          - CHOOSE:默认值,这时候如果有系统统计信息的话会使用CPU成本模型 ,如果没有系统统计信息的话会使用I/O成本模型 。
          - IO :使用基于I/O成本模型 。
          - CPU :使用基于CPU成本模型 。


          对于我们这个例子,是有系统统计信息的,并且使用的是没有负载的系统统计信息(NOWORKLOAD),所以使用的是基于CPU的成本模型计算访问表的成本。简单而言,基于CPU成本模型主要会考虑I/O和CPU两方面开销估算成本。


            总COST = IO_COST+ CPU_COST


            IO_COST主要包括单块读的成本和多块读的成本。


              IO_COST = (#SRDS * SREADTIM + #MRDS * MREADTIM)  SREADTIM 
              其中:
              - #SRDS (NUMBER OF SINGLE BLOCK READS )是单块读的次数 。
              - #MRDS(NUMBER OF MULTI BLOCK READS)是多块读的次数,其值等于表中高水位线以下数据块数除以一次多块读的块数,即#Blks MBRC。
              - SREADTIM(SINGLE BLOCK READ TIME)是单块读平均时间(单位milliseconds 毫秒)。
              - MREADTIM(MULTI BLOCK READ TIME )是多块读平均时间(单位milliseconds 毫秒)。

              CPU_COST可以通过如下方法进行估算。


                CPU_COST=#CPUCycles  (CPUSPEED * 1000 * SREADTIM)
                其中:
                - #CPUCycles 是预估的CPU开销(周期数),可以通过PLAN_TABLE/V$SQL_PLAN的CPU_COST列或者10053 Trace中的Cost_cpu,本例中为Cost_cpu: 28040899。
                - CPUSPEED(CPU cycles per second) 是CPU的频率(速度)。
                - SREADTIM是单块读平均时间(单位milliseconds 毫秒)。


                对于没有负载的系统统计信息(NOWORKLOAD),并不会收集SREADTIM和MREADTIM的值,一般通过如下方法计算其值。

                  SREADTIM = IOSEEKTIM + DB_BLOCK_SIZE  IOTFRSPEED
                  MREADTIM = IOSEEKTIM + (DB_FILE_MULTIBLOCK_READ_COUNT * DB_BLOCK_SIZE) IOTFRSPEED


                  **如果DB_FILE_MULTIBLOCK_READ_COUNT没有显式设置的话,Oracle会使用隐含参数_db_file_optimizer_read_count的值替代DB_FILE_MULTIBLOCK_READ_COUNT,
                  对于本例而言值为8。


                  SQL> select a.ksppinm "PARAMETER",b.ksppstvl "VALUE",a.KSPPDESC "DESCRIPTION"
                  2 from x$ksppi a, x$ksppcv b
                  3 where a.indx = b.indx and
                  4 a.ksppinm like '%_db_file_optimizer_read_count%';


                  PARAMETER VALUE DESCRIPTION
                  -------------------------------------------------- ---------- --------------------------------------------------
                  _db_file_optimizer_read_count 8 multiblock read count for regular clients


                  另外,CPUSPEED即是CPUSPEEDNW的值。
                  CPUSPEED=CPUSPEEDNW

                  结合前面的系统统计信息的部分,我们可以带入如下的值:


                    -----------------------------
                    SYSTEM STATISTICS INFORMATION
                    -----------------------------
                    Using dictionary system stats.
                    Using NOWORKLOAD Stats
                    CPUSPEEDNW: 1096 millions instructions/sec (default is 100)
                    IOTFRSPEED: 4096 bytes per millisecond (default is 4096)
                    IOSEEKTIM: 10 milliseconds (default is 10)
                    MBRC: NO VALUE blocks (default is 8)


                    ====》》》
                    CPUSPEEDNW=1096
                    IOTFRSPEED=4096
                    IOSEEKTIM=10
                    MBRC = 8

                    --初始参数的值

                      SQL> show parameter DB_BLOCK_SIZE


                      NAME TYPE VALUE
                      ------------------------------------ ---------------------- ------------------------------
                      db_block_size integer 8192

                      因此,我们可以计算出单块读和多块读的平均时间。

                        单块读平均时间SREADTIM=10 + 8192/4096 =12  毫秒)
                        多块读平均时间MREADTIM=10 +(8* 8192)/4096 =26 毫秒)

                        另外,通过上面的TRACE内容我们可以得到表中高水位线以下的数据块信息。


                          ***************************************
                          BASE STATISTICAL INFORMATION
                          ***********************
                          Table Stats::
                          Table: EMP1 Alias: E
                          #Rows: 101948 SSZ: 0 LGR: 0 #Blks: 874 AvgRowLen: 50.00 NEB: 0 ChainCnt: 0.00 ScanRate: 0.00 SPC: 0 RFL: 0 RNF: 0 CBK: 0 CHR: 0 KQDFLG: 1
                          #IMCUs: 0 IMCRowCnt: 0 IMCJournalRowCnt: 0 #IMCBlocks: 0 IMCQuotient: 0.000000

                          ====》》》
                          数据块数#Blks = 874
                          多块读#MRDS = #Blks MBRC =874 / 8


                          对于全表扫描(TABLE FULL SCAN)而言,尽管读取表中管理块信息等情况时也可能发生单块读,但成本估算时一般全表扫描可以认为都是多块读,单块读#SRDS为0。但是为了减少优化器的估算误差,Oracle通过隐含参数_table_scan_cost_plus_one来调节全表扫描和索引快速扫描的成本。当_table_scan_cost_plus_one为TRUE时,会默认在计算成本时加1。


                            SQL> select a.ksppinm "PARAMETER",b.ksppstvl "VALUE",a.KSPPDESC "DESCRIPTION"
                            2 from x$ksppi a, x$ksppcv b
                            3 where a.indx = b.indx and
                            4 a.ksppinm like '%_table_scan_cost_plus_one%';




                            PARAMETER VALUE DESCRIPTION
                            ------------------------- ---------- ------------------------------------------------------------
                            _table_scan_cost_plus_one TRUE bump estimated full table scan and index ffs cost by one

                              

                            综上,我们可以进一步计算出全表访问DEPT1表的COST。

                              总COST = IO_COST+ CPU_COST


                              IO_COST =(#SRDS * SREADTIM + #MRDS * MREADTIM) / SREADTIM
                              = #SRDS + #MRDS * MREADTIM/ SREADTIM
                              = 1 + #Blks / MBRC * MREADTIM/ SREADTIM
                              = 1 + 874 / 8 *26 /12
                              = 1 + 236.708333
                              = 238

                              CPU_COST = #CPUCycles / (CPUSPEED * 1000 * SREADTIM)
                              = 28040899 / (1096*1000*12)
                              = 2.13206349

                               

                               所以最终结果的总Cost 为240.13206349左右。

                              与Cost:  240.132964大致相同。


                              后续文章更加精彩,欢迎关注本公众号。

                              ——End——


                              专注于技术不限于技术!

                              用碎片化的时间,一点一滴地提高数据库技术和个人能力。

                              欢迎关注!

                              手把手系列(帮助个人技术成长):

                              手把手教你在Windows 10安装Oracle 19c(详细图文附踩坑指南)

                              在线Oracle SQL学习环境--Live SQL

                              SQL调优和诊断从哪入手?

                              获取SQL执行计划最基础的方法是啥?

                              一学就会的获取SQL执行计划和性能统计信息的方法

                              【SQL】实时SQL监控功能(Real-Time SQL Monitoring)

                              【SQL】历史SQL监控(Historical SQL Monitoring ) 功能(12c)

                              获取历史执行计划:AWR/StatsPack SQL 报告

                              SQL调优和诊断之何时使用何工具?

                              SQL调优和诊断利器之SQLT介绍

                              SQL调优和诊断利器之SQLHC介绍

                              SQL调优和诊断工具之SQL Trace (10046 Event)介绍

                              SQL调优和诊断工具之Optimizer Trace(10053 Event)介绍
                              SQL调优和诊断工具之DBMS_SQLDIAG介绍

                              SQL调优和诊断工具之SQL 相关的动态视图

                              文章转载自SQL和数据库技术,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                              评论

                              暂无图片
                              获得了256次点赞
                              暂无图片
                              内容获得92次评论
                              暂无图片
                              获得了70次收藏