基数、选择性、直方图

Oracle数据库:基数、选择性与直方图解析
本文详细探讨了Oracle数据库中基数、选择性及其对索引性能的影响。介绍了如何评估索引好坏的标准,特别是针对性别列是否需要建立索引的讨论,并讲解了如何查询列的选择性和基数。同时,对直方图的概念进行了概述,并指导如何查看数据库中的直方图信息,解答相关疑问。

一、基数:

 
   一个列中唯一键(Distinct_keys)的个数,如有一个100W行的表,性别列的基数为2 (select distinct gender from test),主键列的基数为100W(select distinct mid from test);

二、选择性:

    基数/总行数所占的百分比,性别 2/100w * 100% 主键 100%  选择性越高 越有利于使用索引
    20~30%就算是比较高了

 2.1、如何判断是一个索引创建的是好还是坏呢? 

     就看他的基数和选择性 如果基数大选择性大 那么使用索引就比较好

 2.2、性别这个列使不使用索引?

    要看情况,从OLTP系统上来说 在选择性低的列上创建索引肯定不适合的, 基数/选择性高的列,适合建立B-Tree索引;
     在OLAP系统中 基数低的列根据需求,有可能会建立bitmap索引

 2.3、如何查看列的选择性和基数呢?

create table test as select * from dba_objects;
create index idx on test(owner); 
--最简单直接的写法是运行下面的语句 但可能会卡死 想象如果一张表30G 上千万行 而segment_size只有10G 
select count(distinct column_name),count(*) total_rows,count(distinct column_name) / count(*) * 100 selectivi
基数估计(Cardinality Estimation)是数据库查询优化中的一个关键环节,它直接影响查询计划的生成和执行效率。基数估计的目标是预测查询操作后结果集的行数(即基数),这对于选择最优的执行计划至关重要。以下是一些与基数估计相关的技术原理和算法: ### 基数估计的基本原理 基数估计是查询优化器在生成执行计划时的重要依据。优化器需要根据表的统计信息(如行数、列的分布等)来估计每个操作的结果大小,从而选择最高效的执行路径。例如,在连接操作中,优化器需要估计连接结果的基数,以决定使用哪种连接算法(如嵌套循环连接、哈希连接或排序合并连接)[^2]。 ### 常见的基数估计算法 1. **直方图(Histogram)** 直方图是一种常用的统计信息表示方法,用于描述数据的分布情况。通过直方图,优化器可以更准确地估计查询条件的选择率,从而得到更精确的基数估计。直方图可以分为等宽直方图、等频直方图和核密度估计直方图等[^3]。 2. **采样(Sampling)** 采样是一种通过从数据集中随机抽取一部分数据来估计整体分布的方法。通过采样,优化器可以在不扫描整个表的情况下,得到较为准确的基数估计。然而,采样的精度受限于样本的大小和分布[^3]。 3. **多维统计(Multi-dimensional Statistics)** 多维统计方法通过考虑多个列之间的相关性来提高基数估计的精度。例如,某些数据库系统会维护列组(Column Group)的统计信息,以捕捉多列之间的联合分布。 4. **机器学习方法** 近年来,机器学习技术被引入到基数估计中。通过训练模型来预测查询结果的基数,机器学习方法可以在某些场景下提供比传统统计方法更高的精度。例如,使用神经网络模型来学习查询模式和数据分布之间的关系[^2]。 ### 基数估计的挑战 基数估计面临的主要挑战包括: - **数据分布的复杂性**:实际数据的分布往往不是均匀的,且可能存在偏斜或异常值,这使得传统的统计方法难以准确估计基数。 - **多列条件的处理**:当查询涉及多个列的条件时,如何准确捕捉列之间的相关性是一个难题。 - **动态数据的变化**:随着数据的频繁更新,统计信息可能变得过时,导致基数估计的不准确[^3]。 ### 基数估计在查询优化中的应用 在查询优化中,基数估计直接影响执行计划的选择。例如,在连接操作中,优化器会根据基数估计选择合适的连接算法。如果估计的基数较小,优化器可能会选择嵌套循环连接;如果基数较大,哈希连接或排序合并连接可能更为合适。此外,基数估计还影响索引的选择和排序操作的代价估算。 ### 示例代码:基于直方图基数估计 以下是一个简单的基于直方图基数估计示例代码,假设我们有一个包含数值数据的列,并使用等宽直方图来估计查询条件的选择率: ```python def estimate_cardinality_with_histogram(data, query_range, num_bins): import numpy as np # 创建等宽直方图 hist, bin_edges = np.histogram(data, bins=num_bins) # 计算查询范围内的桶索引 start_bin = np.digitize(query_range[0], bin_edges) end_bin = np.digitize(query_range[1], bin_edges) # 计算查询范围内的总行数 total_rows = sum(hist[start_bin-1:end_bin]) return total_rows # 示例数据 data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] query_range = (3, 7) num_bins = 5 # 估计基数 cardinality = estimate_cardinality_with_histogram(data, query_range, num_bins) print(f"Estimated cardinality: {cardinality}") ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值