pg 统计信息及索引cost 简介

2024-04-30 22:04
文章标签 统计 索引 信息 简介 pg cost

本文主要是介绍pg 统计信息及索引cost 简介,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

pg 统计信息及索引cost 简介

  • pg 统计信息及索引cost 简介
    • 单列的统计信息
      • 数据采样
        • 对于外部表:
      • 数据统计
    • 索引cost 计算
    • 行数确定

pg 统计信息及索引cost 简介

单列的统计信息

单列的统计信息,通过do_analyze_rel 函数进行生成,主要分为两个部分:

  1. 数据采样
  2. 数据统计

数据采样

随机的采取表中的一部分数据进行分析,如果没有指定采样数(一般都没有),使用default_statistics_target (默认100)进行计算,采样容量为 300 * default_statistics_target (默认30000)。

根据 SIGMOD98 中的论文 Random sampling fo r histogram construction: how much is enough 可以得出这个这个已足够,当当表很大是,仍需调大default_statistics_target 。

采样算法采样两阶段算法,第一阶段采样使用S算法对表中的页面进行随机采样,第二个阶段使用 Z(Vitter)算法,它在第一阶段采样出来的页面的基础上对元组进行采样。

数据采样的两个阶段采用不同的算法是因为当对一个表进行统计分析的时候,它的页面数(块数)是可以准确获得到的,也就是说页面采样是在己知总体容量的基础上进行的。而第二阶段的 Z(Vitter)算法是一种蓄水池算法,它主要解决的是在不知道总体容量的情况下如何进

对于外部表:
  • pg: 通过AnalyzeForeignTable 函数获取采样外部表的函数acquirefunc(没有则warning,同时也获取relpages),然后调用函数获取采样的行,然后对数据进行统计
  • opengauss :通过AnalyzeForeignTable 函数获取采样外部表的函数acquirefunc(没有则warning,同时也获取relpages),但gauss 不使用acquirefunc 获取行, 而是通过AcquireSampleRows采样行(只支持obs,hdfs, obs_cvs, oracle_fdw,pg_fdw,mot,RELKIND_STREAM?支持其他的需要修改代码)

数据统计

分析各个列的统计信息, 对于表达式索引,也会计算表达式值并统计信息。

统计数据会存在pg_statistic 表中,

pages/tuples 会计入对应的表和索引中(Update pages/tuples stats in pg_class, 默认表和索引的行数相同,除非是partial index - 带where条件的索引 )

索引不会使用采样到的pages ,因为这个pages 是表的pages. 而是使用GetOneRelNBlocks 获取的blocks, 作为pages. 对于外表就是0

索引cost 计算

cpu 和 io , 选择率用来确定行数或索引项数

对于seqscan, 选择率用来确定 返回的行数

对于索引扫描,会调用索引的amcostestimate 函数计算索引cost和索引项数目,索引条件的选择率(其实就是列的选择率)用来确定扫描到的索引项数,会基于这个索引项数确定对堆表的io 和cpu cost (pg 索引不是聚簇索引,需要回表查询,除非indexonly)

    amcostestimate:/** @param loop_count 索引作为内表时,需要循环的次数* @[out]indexStartupCost 索引扫描自身的启动代价* @[out]indexTotalCost 索引扫描自身的整体代价* @[out]indexSelectivity 索引扫描的选择率* @[out]indexCorrelation 索引的相关系数* @[out]indexPages 索引page 数,opengauss 没有* */void (*amcostestimate)(PlannerInfo *root, IndexPath *path, double loop_count, Cost *indexStartupCost,Cost *indexTotalCost, Selectivity *indexSelectivity, double *indexCorrelation,double *indexPages)

在btree 中,启动代价为约束中的表达式代价,即计算所有的表达式值的代价(因为在每次扫描前需要计算表达式的值,右值)。

总代价为 io代价和 cpu代价的和。

  • io代价: 索引扫描的执行次数取决于外表的元组数和是否有ScalarArrayOpExpr(有那么num_sa_scans也是扫描次数),所以num_scans = num_sa_scans * num_outer_scans;因为多次扫描可能导致数据被缓存,所以通过如下方式计算IO cost:
        /*   对于外表:在pg 中,index->pages 为0在 opengauss 中,在 build_simple_rel 中会调用 set_local_rel_size,最终调用clamp_row_est 会把index->pages 转换为1, 也即外表上的索引 index->pages 为1*/if (index->pages > 1 && index->tuples > 1)numIndexPages = ceil(numIndexTuples * index->pages / index->tuples);elsenumIndexPages = 1.0;   // numIndexPages 如果小于1 会被设置为1,对于外表即为1double		pages_fetched;/* total page fetches ignoring cache effects */pages_fetched = numIndexPages * num_scans;/* use Mackert and Lohman formula to adjust for cache effects */pages_fetched = index_pages_fetched(pages_fetched,index->pages,(double) index->pages,root);/** Now compute the total disk access cost, and then report a pro-rated* share for each outer scan.  (Don't pro-rate for ScalarArrayOpExpr,* since that's internal to the indexscan.)*/indexTotalCost = (pages_fetched * spc_random_page_cost)/ num_outer_scans;

非多次扫描:indexTotalCost = numIndexPages * spc_random_page_cost;

  • CPU cost:
        qual_op_cost = cpu_operator_cost *(list_length(indexQuals) + list_length(indexOrderBys));indexTotalCost += qual_arg_cost;  //  加上start_cost,qual_arg_cost即start costindexTotalCost += numIndexTuples * num_sa_scans * (cpu_index_tuple_cost + qual_op_cost);  // 加上每个索引项的cpu costopengauss 没有下面的cost:b tree查找非叶子节点的cost:if (index->tuples > 1)		/* avoid computing log(0) */{descentCost = ceil(log(index->tuples) / log(2.0)) * cpu_operator_cost;costs.indexStartupCost += descentCost;costs.indexTotalCost += costs.num_sa_scans * descentCost;}b tree对节点的page 进行二分查找的cost:descentCost = (index->tree_height + 1) * 50.0 * cpu_operator_cost;costs.indexStartupCost += descentCost;costs.indexTotalCost += costs.num_sa_scans * descentCost;
  • 相关系数:单列的通过pg_statistic 获取

行数确定

通过调用get_relation_info (add_base_rels_to_query)获取表及表上索引的page 和行数, 对于表调用estimate_rel_size 获取,对于非部分索引,page 通过RelationGetNumberOfBlocks 获取, tuples 即为表的tuples。 部分索引通过estimate_rel_size 获取,但如果获取的行数大于表的行数,则tuples 设置为表行数。

estimate_rel_size 会去获取关系的blocks ,然后计算pages 和tuples, 之后在make_one_rel 中会调用set_base_rel_sizes 调整rows, 宽度

  • 外表:
        static voidset_foreign_size(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte){/* Mark rel with estimated output rows, width, etc */set_foreign_size_estimates(root, rel);/* Let FDW adjust the size estimates, if it can */rel->fdwroutine->GetForeignRelSize(root, rel, rte->relid);/* ... but do not let it set the rows estimate to zero */rel->rows = clamp_row_est(rel->rows);/* also, make sure rel->tuples is not insane relative to rel->rows */rel->tuples = Max(rel->tuples, rel->rows);}
  • 普通表:
        voidset_baserel_size_estimates(PlannerInfo *root, RelOptInfo *rel){double		nrows;/* Should only be applied to base relations */Assert(rel->relid > 0);nrows = rel->tuples *clauselist_selectivity(root,rel->baserestrictinfo,0,JOIN_INNER,NULL);rel->rows = clamp_row_est(nrows);cost_qual_eval(&rel->baserestrictcost, rel->baserestrictinfo, root);set_rel_width(root, rel);}

这篇关于pg 统计信息及索引cost 简介的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/950038

相关文章

详解如何使用Python从零开始构建文本统计模型

《详解如何使用Python从零开始构建文本统计模型》在自然语言处理领域,词汇表构建是文本预处理的关键环节,本文通过Python代码实践,演示如何从原始文本中提取多尺度特征,并通过动态调整机制构建更精确... 目录一、项目背景与核心思想二、核心代码解析1. 数据加载与预处理2. 多尺度字符统计3. 统计结果可

MySQL 添加索引5种方式示例详解(实用sql代码)

《MySQL添加索引5种方式示例详解(实用sql代码)》在MySQL数据库中添加索引可以帮助提高查询性能,尤其是在数据量大的表中,下面给大家分享MySQL添加索引5种方式示例详解(实用sql代码),... 在mysql数据库中添加索引可以帮助提高查询性能,尤其是在数据量大的表中。索引可以在创建表时定义,也可

Linux查看系统盘和SSD盘的容量、型号及挂载信息的方法

《Linux查看系统盘和SSD盘的容量、型号及挂载信息的方法》在Linux系统中,管理磁盘设备和分区是日常运维工作的重要部分,而lsblk命令是一个强大的工具,它用于列出系统中的块设备(blockde... 目录1. 查看所有磁盘的物理信息方法 1:使用 lsblk(推荐)方法 2:使用 fdisk -l(

SpringBoot如何对密码等敏感信息进行脱敏处理

《SpringBoot如何对密码等敏感信息进行脱敏处理》这篇文章主要为大家详细介绍了SpringBoot对密码等敏感信息进行脱敏处理的几个常用方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录​1. 配置文件敏感信息脱敏​​2. 日志脱敏​​3. API响应脱敏​​4. 其他注意事项​​总结

rust 中的 EBNF简介举例

《rust中的EBNF简介举例》:本文主要介绍rust中的EBNF简介举例,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1. 什么是 EBNF?2. 核心概念3. EBNF 语法符号详解4. 如何阅读 EBNF 规则5. 示例示例 1:简单的电子邮件地址

MySQL索引失效问题及解决方案

《MySQL索引失效问题及解决方案》:本文主要介绍MySQL索引失效问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录mysql索引失效一、概要二、常见的导致MpythonySQL索引失效的原因三、如何诊断MySQL索引失效四、如何解决MySQL索引失

Python 异步编程 asyncio简介及基本用法

《Python异步编程asyncio简介及基本用法》asyncio是Python的一个库,用于编写并发代码,使用协程、任务和Futures来处理I/O密集型和高延迟操作,本文给大家介绍Python... 目录1、asyncio是什么IO密集型任务特征2、怎么用1、基本用法2、关键字 async1、async

springboot实现配置文件关键信息加解密

《springboot实现配置文件关键信息加解密》在项目配置文件中常常会配置如数据库连接信息,redis连接信息等,连接密码明文配置在配置文件中会很不安全,所以本文就来聊聊如何使用springboot... 目录前言方案实践1、第一种方案2、第二种方案前言在项目配置文件中常常会配置如数据库连接信息、Red

Pandas中统计汇总可视化函数plot()的使用

《Pandas中统计汇总可视化函数plot()的使用》Pandas提供了许多强大的数据处理和分析功能,其中plot()函数就是其可视化功能的一个重要组成部分,本文主要介绍了Pandas中统计汇总可视化... 目录一、plot()函数简介二、plot()函数的基本用法三、plot()函数的参数详解四、使用pl

Pandas统计每行数据中的空值的方法示例

《Pandas统计每行数据中的空值的方法示例》处理缺失数据(NaN值)是一个非常常见的问题,本文主要介绍了Pandas统计每行数据中的空值的方法示例,具有一定的参考价值,感兴趣的可以了解一下... 目录什么是空值?为什么要统计空值?准备工作创建示例数据统计每行空值数量进一步分析www.chinasem.cn处