-
SQL中含大写别名,查询结果会转成小写,导致字段匹配不上,其他数据库没有这种处理,为何会有这种设计?该如何解决?
-
11月16日,华为开发者布道师活动-openGuass的AI特性在电子科技大学清水河校区立人楼B101成功举行。本次活动邀请了电子科技大学计算机科学与工程学院教授、华为开发者布道师生态发展计划教师布道师孙明老师作为主讲嘉宾。孙老师深入介绍了openGauss数据库AI4DB部分的内容,详细介绍了X-Tuner:参数调优与诊断 、SQLdiag慢SQL发现 、Index-advisor:索引推荐 、Anomaly-detection:数据库指标采集、预测与异常监控 、PredictorAI查询时间预测等openGauss数据库与人工智能融合的技术。最后带领在场的开发者同学们在安装完成的openGauss数据库上,使用AI4DB的功能,对数据库参数进行优化,对TPCH测试中的SQL语句进行优化。
-
1 数据库智能化发展史云原生为迎接智能化提供了基础条件,智能化是GaussDB的新的牵引方向,两者相辅相成,互相促进。在智能化出现之前,数据库的运维管理主要依赖分层解耦、化繁为简方式来治理,通过人工服务对单点的业务进行管理。但在云化环境中,一个Region纳管上万实例,仅靠人工很难满足业务诉求,这就促成智能与数据库在云原生的架构和应用中释放的新的研发方向。GaussDB基于智能化(AI)技术,打造AI4DB和DB4AI两大技术高地,重构数据库内核核心组件,提升数据库管理和优化技术,满足数据库科学家对普惠AI的诉求。AI4DB技术利用机器学习,基于海量运行期数据及负载数据,形成智能解决方案,自动化处理各项任务,加速运维和诊断优化效率提升。DB4AI通过数据库使能AI,满足数据科学家在数据治理方面的诉求,仅通过简易SQL调用,即刻完成机器学习算法的训练和推荐,实现人人会AI,人人用AI的普惠应用。如上图所示,GaussDB AI4DB领域包含两个方面的核心子系统:自治运维系统及智能优化器(ABO)。其中自治运维系统提供用户和DBA进行数据库系统的智能化运维管理能力,包括自监控、自诊断、自调优等方面端到端的运维管理能力,主要目标是提升系统的运维诊断效率,让数据库系统更高效和可靠。智能优化器是将AI技术嵌入到数据库内核优化器引擎,实现智能基数估计、智能计划管理和智能代价模型等功能,提升查询语句生成计划的准确性和提供查询语句的执行效率。GaussDB DB4AI领域指在数据库内实现机器学习引擎,即库内AI引擎。通过在数据库内置常用机器学习算法,把AI算法作为执行器中的执行算子在语句执行中实现,对外提供训练和推理的简易SQL语法方便用户调用。同时,在数据库内置模型管理能力,用户训练好的模型可以存储在系统表中,方便快速推理调用。在训练数据准备阶段,通过数据集管理能力,分为多个版本来保证数据训练的一致性,便于训练算法的调优。2 自治运维技术在数据库自治运维技术领域,主要分为两条技术路线。其一是以Oracle为主的老牌数据库厂商,构建运维及生命周期管理统一逃课,实现大规模的数据库智能化管理能力;对用户通过运维工具指导业务快速升级和排障,对业务通过内置的优化诊断套件和多维度报表,快速定位性能瓶颈问题和实现SQL的快速优化。这种方案在单一集群或小规模集群是高效的,通过DBA能力复制,可快速完成运维技术的应用。另一种是以新兴云厂商为主,构建基于云化设施和环境的自治运维技术。尽管各家的技术不近统一,主体思路是一致的,即尽可能通过一套运维管理系统,纳管云化多套环境,通过机器学习技术和海量数据,训练高效诊断和优化模型,形成标准化运维套路。GaussDB基于机器学习技术和云上海量数据信息,构建领先的自治运维管理系统,通过成熟算法实现负载感知、环境感知和数据感知,为数据库提供自监控、自诊断、自调优、自安全的能力,为客户和DBA提供极佳的运维管理体验。上图为GaussDB的自治运维系统整体框图。数据采集层实现多维指标的数据采集,采集频率根据内容不同可分为秒级采集和分钟级采集。其中秒级采集包括操作系统资源信息采集和数据库实例信息采集,例如操作系统层面CPU、内存、IO读写、网络资源信息采集,数据库实例状态、数据库内关键指标(内存、连接数、TPS、QPS、读写频率等);分钟级采集包括审计日志采集、数据库日志采集和全量SQL流水采集等。自治运维平台提供采集程序(Agent进程),可部署在数据库服务侧或者远端,连接数据库实例或所在服务器,采集上述指标;若客户系统配置普罗米修斯进行信息采集,可实现相应的exporter,在其中内置数据库多维度指标采集方法以及数据清理方案,实现与普罗米修斯平台对接。数据库采集端程序需要部署在同数据库进程所在物理节点时,若数据库为多节点集群环境,每个物理节点可部署一个Agent进程采集端(或者普罗米修斯采集端)。数据库采集端程序通常占用资源很少,通过配置文件可以制定不同指标采集频率,以免占用资源影响数据库业务正常运行。数据计算层提供数据存储、数据分析及元数据管理能力。其中数据存储用于接收来自数据采集层发生来的数据,存储数据源可以是多种维度或者类型,包括普罗米修斯、时序数据库(OpenTSDB等)、MongoDB、SQLite等,自治运维服务内置对接接口,每个自治服务模块与存储数据源的交互,获取数据并进行分析处理。在企业实际应用时,可根据需要选择不同的存储组件和大数据处理组件,例如普罗米修斯+时序数据库,或者kafka+时序数据库等方案。在数据计算层除了时序存储数据库外,还可以设计其他存储单元,例如算法模型库和故障规则库。其中算法模型库存储自治管理服务生成的AI模型,例如参数推荐训练模型;在算法模型库中,可以存储传统机器学习(例如监督学习)模型、强化学习模型。故障规则库是记录数据库常见故障案例,将这些案例通过拆解和分析,生成规则引擎。自治服务层在用户维度,可以分为SQL诊断和调优、自治安全、数据库运维。其中SQL诊断和调优提供多种SQL治理和调优能力,包括慢SQL诊断、SQL表现评估、智能索引推荐、智能查询重写等服务。自治安全通过AI技术实现敏感信息发觉、SQL注入检测和异常行为分析。数据库运维能力实现在数据库系统、OS系统和数据库集群层面的运维和调优,其中数据库系统服务包括数据库参数智能推荐、智能巡检、数据库分布键推荐和智能业务调度;在操作系统层面,实现慢盘检测和恢复、网络丢包检测;在数据库集群层面,基于故障或者负载需求,提供自动扩缩容、异常节点修复服务。自治运维服务最终需要通过管控网页界面形式对外呈现,方便用户直观感受运维管理带来的效果。在展示界面方面,多指标结合AI趋势预测,可给出后续时段的数据走向。同时为方便用户系统观察集群状态,提供健康指数报告和详细综合报告。健康指数报告给出当前系统的健康评分等级,默认80分以上属于运行健康状况,小于60分则存在严重隐患,急需修复。综合报告详细描述系统各维度信息,包括集群状态、负载运行情况、常见数据库指标项信息。2.1 智能监测GaussDB提供500+指标的智能监测,通过对数据库指标、操作系统指标和运行日志的采集,拉取采集数据至时序数据库存储,便于后续进行异常侦测和问题定位。为了快速支撑各粒度的多维度指标采集,部署多个采集程序,例如数据库指标采集程序openGauss-exporter、操作系统指标采集程序node-exporter、本地执行采集程序cmd_exporter以及数据二次处理程序reprocessing-exporter等。GaussDB智能监测程序采取服务化方式部署,通过RPC通道(默认Https协议,且校验数据库用户名密码,不存在空密码访问情况)实现,可以获取数据库的即时信息,也可以向数据库下发执行动作(需要用户提供的用户具备执行权限,具体数据库用户由用户指定)。时序数据处理支持多种时序库存,例如普罗米修斯、Influxdb等,尽管对接接口协议不同,但实现方式类似。后面以普罗米修斯时序库和采集程序进行举例,说明智能监控的方法和实现方案。下图为智能监测方案的执行时序图。数据采集的实现过程:(1)Exporter 的数据采集原理如上图所示,采集过程是pull的形式,即由Prometheus 主动发起数据刮取(scrape)请求,而后exporter再想被监控服务(可以是数据库服务、Linux等)发起查询请求,由其通过http(s) 协议展示给Prometheus;(2)通过Prometheus 框架,按照Prometheus协议即可实现对应的exporter,该实现过程类似一个插件,通过Prometheus 提供的SDK(如prometheus-client库)即可完成开发过程;(3)所采集的指标项通过用户给定的配置文件解析获得,不需要在exporter中固化;(4)实现的exporter主要有两个,一个是openGauss-exporter,用于监控数据库实例,从其上面抓取数据;另一个是reprocessing-exporter, 用于对Prometheus已经采集到的数据进行二次加工。两个exporter是各自独立的进程。(5)openGauss-exporter 是需要输入待监控数据库的登录密码的,该密码通过shell命令的配置参数输入。其中,在命令行中通过内存覆盖的技术擦除了命令行中的密码,避免了通过 ps –ux 等泄漏密码的可能。(6)为进一步保障采集数据的安全性,exporter采集的数据源由用户手动配置,默认配置文件不涉及敏感数据,仅采集数据库性能相关指标;在网络协议方面,默认支持采用https协议,用户显性给定证书文件路径,并在Prometheus-server侧进行配置exporter采集工具和用户不涉及交互,所有SQL执行都有程序本身实现,不涉及SQL注入问题。数据采集存储在时序数据库后,将进入趋势预测和异常检测模块,便于客户提前发现潜在问题或者实时发现系统中的异常问题。2.2 趋势预测趋势预测功能模块主要实现基于历史时序数据预测未来时序变化趋势。该模块框架解耦,可以实现不同预测算法的灵活替换,并且该模块功能可以实现不同特征时序的算法自动选择,支持线性特征时序预测LR回归算法和非线性特征预测ARIMA算法。目前该模块可以覆盖线性时序、非线性时序和周期时序的准确预测。时序预测模块和异常检测模块作为自监控的两个核心组件,通过采集程序获取数据后,在检测器阶段进行时序预测及异常检测,数据流转的流程如下:数据获取和数据分析是一个相对于数据库环境独立的工具组件,包括Agent、检测器等子模块。其中Agent是部署在数据库主机环境上的,用于采集数据库中的性能指标,并通过网络,将其传送给远端检测器模块,远端检测器模块负责对采集到的性能指标数据进行收集、存储与检测。Agent模块分为三个子模块,分别是Source、Channel以及Sink,各个组件之间可插拔、可扩展。其中数据收集端Source,用于直接监控数据库系统,并从数据库系统中采集信息;数据缓存器Channel,可以理解为缓存区,用来保存Source处捕获的数据,是一个FIFO的队列。Source捕获的数据会Push到Channel中,而后Sink组件消费由Source产生的数据。Channel缓存在内存中,为了防止OOM,具有容量上限,当超过容量上限时,过多的元素会被禁止放入队列。数据处理及外发Sink,负责从Channel消费数据,然后将数据从Channel中清除,以指定数据格式进行外发,将数据存储到外部存储系统。在数据从Channel端到Sink端的过程中,加入了JSON wrapper 和flow controller两个中间件,分别对应了JSON格式封装、流量控制功能。其中,由于Agent架构对限流功能天然友好,Channel充当缓存功能,实现漏桶算法进行限流。Sink上支持类似这种pipeline模式,以便后续对上传过程进行控制,提供可扩展能力。从Agent发送到检测器的网络通信协议默认为https,默认证书在部署时由部署脚本生成。检测器主要包括三个部分,分别是存储模块、时序预测模块、异常检测模块。本章节重点描述时序预测模块,异常检测模块在后续单独描述。时序预测模块的执行流程如下:时序预测模块提供了两种基本的预测模型,分别是线性模型和深度学习模型。另外系统给用户指定了三种预测模式,分别是decompose、ensemble、hybrid。Decompose代表分解预测模式,ensemble代表整体预测模式,hybrid代表混合预测模式,算法步骤为:1. 首先获取训练数据,算法会判断数据的线性相关系数是否大于指定的阈值(系统默认0.9),如果大于阈值,则会选择线性预测模型(linear regressor),否则会选择循环神经网络预测模型(RNN)。2. 如果用户选择decompose预测模式,系统会调用是时序分解算法将序列分解成周期项、趋势项、残差项,然后调用模型对趋势项进行训练,得到趋势的预测结果。对于周期不需要预测,可以根据周期性递推得到未来周期项。对于残差,系统基于统计学原理,取25%和75%分位作为残差项的上下限。最终预测结果为趋势项、周期项和残差项的和。3. 如果用户选择ensemble预测模式,系统会直接对数据进行训练,然后进行预测,得到预测结果和模型评分。4. 如果用户选择的hybrid模式,系统会串行的执行decompose和ensemble两种预测模式流程,同时根据它们最终模型评分的高低选择最优的预测结果。如果用户真实采集到的信息与时序预测的结果出现较大偏差(大于预设阈值),则认为当前情况出现异常,执行报警逻辑。2.3 异常检测异常检测模块主要基于统计方法来实现时序数据来发现数据中存在的可能的异常情况。该模块框架解耦,可以实现不同异常检测算法的灵活替换,而且该模块功能可以根据时序数据的不同特征来自动选择算法,支持异常值检测、阈值检测、箱型图检测、梯度检测、增长率检测、波动率检测和状态转换检测。异常检测模块实现的流程图如下:在异常检测模块执行过程中,主要包括以下步骤:(1)获取异常根因以及对应异常指标配置从配置中读取需要诊断的根因名称以及每种根因对应的指标名称;下表列出部分根因对应的指标信息。(2)获取异常根因特征库配置系统利用实验环境模拟以及DBA专家经验为每个根因指定一个特征向量集合V={v1,v2,…,vi},其中vi是一个二进制独热(one-hot)编码向量,1表示该根因会导致特定指标出现某种异常,0则表示不会导致该异常。(3)获取异常时刻有两种方式触发异常根因诊断,一种是数据监控平台会定时搜索查找关键性能指标(KPI,包括QPS,TPS,查询时延等)异常的时间段,监控平台会综合利用不同的序列异常检测算法,通过对于不同异常类型的分析得出是否是异常的结论;另一种是用户手动设置诊断时间触发诊断。(4)生成异常特征向量对于异常时刻T,系统抽取[T-3600s,T+200s]区间范围内的所有指标序列;通过调用监控层的异常检测算法检测出异常类型,并转换成独热编码(one-hot),每一位表示一个特定的指标异常。(5)查找Top-K根因针对生成的特征向量,系统从异常特征库中获取近似包含的所有特征向量,并且根据相似度返回最有可能的K个特征向量对应的异常根因。(6)输出根因和置信度系统将TopK的根因的相似度使用Softmax函数进行归一化,归一化之后给出每个根因的概率作为置信度进行输出。异常检测的系统详细设计如下:(1)关键指标获取针对异常场景,系统从系统监控层分别拉取如下指标:(2)特征向量抽取特征向量是一个独热编码向量,其中每一位表示一个指标序列的一个异常,异常特征类型考虑如下:(3)近似包含匹配向量v近似包含定义为, 是一个在(0,1]区间内的阈值。在异常特征库中,每个异常根因包含若干特征向量,只要和其中一个存在近似包含关系,那么就可以认为存在该根因。比如对于数据库锁竞争,一共考虑三种指标,假设每种指标有4种异常类型,那么向量v一共有12位。通过实验我们发现数据库锁竞争会导致锁数量突然上升(spike up),锁等待时间剧烈抖动(volatility shift),由于锁超时导致的执行取消的数量也增加(level shift)。所以特征库中针对锁竞争的特征向量集合可以表示为[(1,0,0,0,0,0,1,0,0,1,0,0)]。当生产环境中这三个指标出现类似的异常(1,0,0,1,0,0,1,0,0,1,0,0),那么由于近似包含(近似度为1),可以判断存在锁竞争异常。(4)通过相似度计算置信度置信度表示每种异常根因的后验概率,这种概率要满足三个条件,(1)系统返回的K个根因的总概率之和要为1;(2)每个根因的概率取值范围是[0,1];(3)每种根因的置信度要求具有区分度。因此,我们采用softmax对置信度进行归一化计算,假设返回的K个相似度分别是, 计算公式如下:以上内容介绍了GaussDB数据库智能化发展史,并从智能检测、趋势预测、异常检测等三方面对GaussDB的自治运维技术进行了解读,下篇将从日志分析、慢SQL发现、慢SQL诊断、集群故障根因诊断等方面继续介绍GaussDB的自治运维技术,敬请期待!
-
在数据系统中,数据分区是在一个实例内部按照用户指定的策略对数据做进一步的数据切分,将表按照指定规则划分为多个数据互不重叠的部分。从数据分区的角度来看是一种水平分区(horizontal partition)分区策略方式。分区表增强了数据库应用程序的性能、可管理性和可用性,并有助于降低存储大量数据的总体拥有成本。分区允许将表、索引和索引组织的表细分为更小的部分,使这些数据库对象能够在更精细的粒度级别上进行管理和访问。GaussDB Kernel提供了丰富的分区策略和扩展,以满足不同业务场景的需求。由于分区策略的实现完全由数据库内部实现,对用户是完全透明的,因此它几乎可以在实施分区表优化策略以后做平滑迁移,无需潜在耗费人力物力的应用程序更改:(1)改善查询性能,对分区对象的查询可以仅搜索自己关心的分区,提高检索效率(2)增强可用性,如果分区表的某个分区出现故障,表在其他分区的数据仍然可用。(3)方便维护,如果分区表的某个分区出现故障需要修复数据,只修复该分区即可。常见数据库支持的分区表为范围分区表、列表分区表、哈希分区表、间隔分区、组合分区(a.w.k 组合分区)。(1)范围分区(Range Partition):将数据基于范围映射到每一个分区,这个范围是由创建分区表时指定的分区键决定的。这种分区方式是最为常用的。范围分区功能,即根据表的一列或者多列,将要插入表的记录分为若干个范围(这些范围在不同的分区里没有重叠),然后为每个范围创建一个分区,用来存储相应的数据。(2)列表分区(List Partition):将数据基于各个分区内包含的键值映射到每一个分区,分区包含的键值在创建分区时指定。列表分区功能,即根据表的一列,将要插入表的记录中出现的键值分为若干个列表(这些列表在不同的分区里没有重叠),然后为每个列表创建一个分区,用来存储相应的数据。(3)哈希分区(Hash Partition):将数据通过哈希映射到每一个分区,每一个分区中存储了具有相同哈希值的记录。(4)间隔分区(Interval Partition):可以看成是范围分区的一种增强和扩展方式,相比之下间隔分区定义分区时无需为新增的每个分区指定上限和下限值,只需要确定每个分区的长度,实际插入的过程中会自动进行分区的创建和扩展。间隔分区在创建初始时必须至少指定一个范围分区,范围分区键值确定范围分区的高值称为转换点,数据库为值超出该转换点的数据自动创建间隔分区。每个区间分区的下边界是先前范围或区间分区的非包容性上边界。(5)二级分区(Sub Partition,也叫组合分区)是基本数据分区类型的组合,将表通过一种数据分布方法进行分区,然后使用第二种数据分布方式将每个分区进一步细分为子分区。给定分区的所有子分区表示数据的逻辑子集。常见的二级分区组合由Range、List、Hash组成。分区表对查询性能最大的贡献是分区剪枝优化技术,数据库SQL引擎会根据查询条件,只扫描特定的部分分区。分区剪枝是自动触发的,当分区表查询条件符合剪枝场景时,会自动触发分区剪枝。根据剪枝阶段的不同,分区剪枝分为静态剪枝和动态剪枝,静态剪枝在优化器阶段进行,在生成计划之前,数据库已经知道需要访问的分区信息;动态剪枝在执行器阶段进行(执行开始/执行过程中),在生成计划时,数据库并不知道需要访问的分区信息,只是判断“可以进行分区剪枝”,具体的剪枝信息由执行器决定。注意,分区表由于相比普通表多了一层分区选择的处理逻辑,一般而言在数据导入场景下会有一定的性能损耗。
-
命名规范数据库对象(库名、表名、字段名、索引名)命名建议全部使用小写字母开头,后面跟字母或者数字,数据库对象(库名、表名、字段名、索引名)名字长度建议都不要大于32字节。 数据库名称不能使用特殊字符("",.,$,,/,*,?,~,#,:,|")和空字符\0,数据库名称不能使用admin,local,config。 数据库集合名称建议使用字母和下划线组合,不能以system为前缀,<数据库名>.<集合名称> 总长度不超过120字符。索引设计规范索引创建,可以避免全表扫描,有效地提高查询命令的执行效率。索引字段的长度不能超过512字节,索引名称长度不能超过64字符,单个复合索引所包含字段数最多不能超过16个。<数据库名>.<集合名>.$<索引名>的总长度不能超过128字符。在高选择性字段上的创建索引。在低选择性字段上查询会返回较大的结果集。尽量避免返回较大的结果集。对集合的写操作同时会操作集合上的索引,从而触发更多的IO操作,集合上的索引数量不要超过32。 不要创建不会被使用到的索引,因为DDS会加载索引到内存,无用索引加载到内存会浪费内存空间因业务逻辑变化而产生的无用索引也要及时清理。索引创建必须使用后台创建索引,禁止前台创建索引。业务中查询,排序条件的key一定要创建索引,如果建立的是复合索引,索引的字段顺序要和这些关键字后面的字段顺序一致,否则索引不会被使用。不要基于复合索引的靠前字段再创建索引。复合索引可以被用于一个索引中主要字段的查询。例如,对于复合索引(firstname,lastname)可以用于在firstname上的查询,再创建一个单独firstname的索引是不必要的。创建索引会消耗较多的IO与计算资源,建议在业务低谷期进行索引创建,禁止同时并发创建超过5条索引。如果需要对同一集合创建多个索引,建议使用createIndexes命令一次性下发多条索引,可以减少性能损耗。分片设计规范对于使用DDS分片集群,建议尽可能的使用分片集合以充分利用性能,详情请参见设置数据分片以充分利用分片性能。分片集合使用上建议如下:对于大数据量(数据量过百万),并有较高读写请求的业务场景,数据量随着业务量增大而增大的,建议采用分片。对于采用hash分片的集合,需要根据业务后面实际数据量大小,采用预分片,提前预置chunk数量,减少自动均衡和分裂对业务运行造成影响。对于非空集合开启分片,应将均衡器的开启时间窗放在业务空闲时,避免分片间均衡数据与业务冲突影响性能。设置时间窗口的API接口详情请参见设置集群均衡活动时间窗。需要基于分片键排序查询且增加数据时可以分布均匀建议使用范围分片,其他使用哈希分片。 合理设计shard key,防止出现大量的数据使用相同shard key,导致出现jumbo chunk。使用分片集群,执行dropDatabase后,一定要执行flushRouterConfig命令,详情请参见如何规避dds mongos路由缓存缺陷。业务的update请求需要注意与片键相适配。在使用分片表时,如果出现如下场景则update请求会报错,并返回“An upsert on a sharded collection must contain the shard key and have the simple collation”。update请求的filter中未携带片键字段且选项multi:falseset中未携带片键字段且选项upsert:true
-
GaussDB开发规范数据库连接使用DDS时,可能会遇到因为Mongod/dds mongos的连接数满了,导致客户端无法连接的问题。在Mongod/dds mongos的服务端,收到一个新的连接由一个单独的线程来处理,每个线程配置了1MB的栈空间,当网络连接数太多时,过多的线程会导致上下文切换开销变大,同时内存开销也会上涨。客户端连接数据库的时候,要计算业务一共有多少个客户端,每个客户端配置的连接池大小是多少,总的连接数不要超过当前实例能承受的最大连接数的80%。客户端与数据库的连接应尽量保持相对稳定的状态,每秒新增连接数建议保持在10以下。 建议客户端的连接超时时间至少设置为最大业务执行时长的3倍。对于副本集实例,客户端需要同时配置主备节点的IP地址;对于集群实例,至少配置两个dds mongos的IP地址。DDS默认提供rwuser用户,使用rwuser用户登录时认证库必须是admin。可靠性write concern设置规则:对于关键业务,write concern设置为{w:n},n>0,数字越大,一致性实现更好,但性能较差。w:1表示实际写入主节点完成返回。w:1,journal:true表示写主节点和日志后返回。w:majority表示大多数备节点写入后返回。说明: 如果没有以w:majority写入数据,则发生主备倒换时,未同步到备机的数据有丢失风险。对于可靠性有较高要求的,建议采用3AZ部署的集群。性能相关规范 业务程序禁止执行全表扫描的查询。执行查询时,只选择需要返回的字段,不需要的字段不要返回。从而减少网络和进程处理的负载,修改数据时,只修改变化需要修改的字段,不要整个对象直接存储全部修改。避免使用$not。DDS并不会对缺失的数据进行索引,因此$not的查询条件将会要求在一个结果集中扫描所有记录。如果$not是唯一的查询条件,会对集合执行全表扫描。用$and时把匹配最少结果的条件放在最前面,用$or时把匹配最多结果的条件放在最前面。单个实例中,数据库的总的个数不要超过200个,总的集合个数不要超过500个。集合数量过多会导致内存压力变高,并且集合数量多会导致重启以及主备倒换性能变差,影响紧急情况下的高可用性能。业务上线前,一定要对数据库进行性能压测,评估业务峰值场景下,对数据库的负载情况。 禁止同时执行大量并发事务,且长时间不提交。业务正式上线前, 所有的查询类别,都应该先执行查询计划检查查询性能。建议 每个连接在后台都是由一个单独线程处理,每个线程会分配1MB的栈内存。所以连接数不宜过多,否则会占用过多的内存。使用连接池,避免频繁的建立连接和断开连接,否则会导致CPU过高。减少磁盘读写:避免使用不必要的upsert命令,避免查询不必要的数据。优化数据分布:对数据进行分片,同时分散热点数据,均衡地使用实例资源。如何进行数据分片,请参见设置数据分片。 减少锁冲突:避免对同一个Key过于频繁地操作。减少锁等待:避免前台创建索引。注意开发过程中对集合的每一个操作都要通过执行explain()检查其执行计划,如:db.T_DeviceData.find({"deviceId":"ae4b5769-896f"}).explain(); db.T_DeviceData.find({"deviceId":"77557c2-31b4"}).explain("executionStats");对于查询而言,因为覆盖查询不需要读取文档,而是直接从索引中返回结果,这样的查询性能好,所以尽可能使用索引覆盖查询。如果explain()的输出显示indexOnly字段为真,则说明这个查询就被一个索引覆盖。执行计划解析:看执行时间:executionStats.executionStages.executionTimeMillisEstimate和executionStats.executionStages.inputStage. executionTimeMillisEstimate时间越短越好。executionStats.executionTimeMillis表示执行计划选择和执行的所有时间。executionStats.executionStages.executionTimeMillisEstimate表示执行计划的执行完成时间。executionStats.executionStages.inputStage. executionTimeMillisEstimate表示执行计划下的子阶段执行完成时间。看扫描条数:三个条目数相同为最佳。executionStats. nReturned表示匹配查询条件的文档数。executionStats .totalKeysExamined表示索引扫描条目数。executionStats .totalDocsExamined表示文档扫描条目数。看Stage状态,性能较好的Stage状态组合如下。Fetch+IDHACK Fetch+ixscan Limit+(Fetch+ixscan) PROJECTION+ixscan如果cursor不使用了要立即关闭。由于cursor在10分钟内不活动,就会关闭,立即手动关闭会节省资源。4.2版本分布式事务使用规则 Spring Data MongoDB不支持事务报错后重试机制,如果客户端使用Spring Data Mongo作为连接MongoDB的客户端,需要依照Spring Data Mongo的参考文档,使用Spring Retry进行事务的重试操作。分布式事务操作数据的大小不能超过16MB。备份相关注意事项备份期间应避免进行DDL操作,规避备份失败的风险。 GaussDB官网
-
表的选择 1.行存储 默认创建表的类型。数据按行进行存储,即一行数据是连续存储。适用于对数据需要经常更新的场景 gaussdb=# CREATE TABLE customer_t1 ( state_ID CHAR(2), state_NAME VARCHAR2(40), area_ID NUMBER ); --删除表 gaussdb=# DROP TABLE customer_t1; 2列存储 数据按列进行存储,即一列所有数据是连续存储的。单列查询IO小,比行存表占用更少的存储空间。适合数据批量插入、更新较少和以查询为主统计分析类的场景。列存表不适合点查询。 gaussdb=# CREATE TABLE customer_t2 ( state_ID CHAR(2), state_NAME VARCHAR2(40), area_ID NUMBER ) WITH (ORIENTATION = COLUMN); --删除表 gaussdb=# DROP TABLE customer_t2; 3行存表和列存表的选择 更新频繁程度 数据如果频繁更新,选择行存表。 插入频繁程度 频繁的少量插入,选择行存表。一次插入大批量数据,选择列存表。 表的列数 表的列数很多,选择列存表。 查询的列数 如果每次查询时,只涉及了表的少数(<50%总列数)几个列,选择列存表。 压缩率 列存表比行存表压缩率高。但高压缩率会消耗更多的CPU资源。
-
oracle的"CONSTRAINT "CK_AZ_ITF_DATA_PARTITION" CHECK (ITF_DATA IS JSON(STRICT)) ENABLE"在gaussdb集中式中如何实现同等转换, json(strict) 这个在gaussdb中不支持,在gaussdb是用函数替代吗。类似如下:1. 创建一个检查 JSON 格式的函数: CREATE OR REPLACE FUNCTION is_json(p_data TEXT) RETURNS BOOLEAN AS $$ BEGIN -- 尝试将输入的数据解析为 JSON EXECUTE 'SELECT CAST(' || quote_literal(p_data) || ' AS JSON);'; RETURN TRUE; EXCEPTION WHEN others THEN RETURN FALSE; END; $$ LANGUAGE plpgsql; 2. 使用该函数创建 CHECK 约束: ALTER TABLE your_table_name ADD CONSTRAINT CK_AZ_ITF_DATA_PARTITION CHECK (is_json(ITF_DATA)); 问题:我这个函数和oracle那个json(strict)是完全等价的吗,如果不符合要求,应该怎样解决呢
-
[问题求助] case语句报错: ERROR: CASE types integer and interval cannot be matched Position: 642 Where: referenced column: XXX在执行一个查询语句中,包含case语句,是以前oracle的sql,迁移到高斯执行报错:SELECT CASE WHEN dep_start_date > '2024-11-01 00:00:00' THEN ( to_date( dep_start_date, 'yyyy-mm-dd' ) - to_date( '2024-11-30 23:59:59', 'yyyy-mm-dd' ) + 0 ) + 1 ELSE 30 END days_calFROM fa_cardhistory;报错信息:
-
数据库版本:gaussdb (GaussDB Kernel 503.1.0.sPc2000 build 8b622ce7) 使用gorm postgres最新驱动连接,提示:failed to receive message(AuthenticationSASL body is invalid unterminated string)连接dsn格式: host=127.0.0.1 user=admin dbname=test sslmode=disable password=admin port=5432
-
tpops添加主机,检查python不通过,怎么回事
-
select oid,relfilenode,relname from pg_class where relname ='teacher'; oid | relfilenode | relname -------+-------------+--------- 17530 | 17542 | teacher然而在操作系统里面,只找到17542这个文件,没有像_vm,_fsm这些文件[Ruby@gauss-dis-134 base]$ find ./ -name 17542* ./17325/17542像在postgresql,openGauss,都是有_fsm,_vm的文件的
-
在postgresql或者openGauss中,数据文件目录的base目录下,名称和oid都是一一对弈对应的,如:openGauss=# select oid,datname from pg_database; oid | datname -------+------------- 1 | template1 16398 | db_web_data 15649 | template0 16400 | db_test2 16399 | db_test1 15654 | postgres 16405 | db_test123对应着文件系统的目录[omm@txy base]$ ls -ls total 120 20 drwx------ 2 omm dbgrp 20480 Oct 12 10:15 1 16 drwx------ 2 omm dbgrp 16384 Oct 12 10:15 15649 16 drwx------ 2 omm dbgrp 16384 Nov 3 23:24 15654 16 drwx------ 2 omm dbgrp 16384 Oct 16 15:44 16398 16 drwx------ 2 omm dbgrp 16384 Oct 23 17:03 16399 16 drwx------ 2 omm dbgrp 16384 Oct 23 17:03 16400 16 drwx------ 2 omm dbgrp 16384 Oct 23 17:25 16405 4 drwx------ 2 omm dbgrp 4096 Oct 12 10:14 pgsql_tmp但是在gaussdb,我发现并不是一样的gaussdb=> select oid,datname from pg_database; oid | datname -------+------------ 1 | template1 14942 | template0 17325 | db_ora 17457 | db_conn10w 17458 | db_default 14948 | postgres 16809 | test在文件目录里面反而是这些?[Ruby@gauss-dis-133 base]$ ls -lsa total 160 4 drwx------ 10 Ruby Ruby 4096 Nov 9 14:29 . 4 drwx------ 22 Ruby Ruby 4096 Nov 9 14:51 .. 16 drwx------ 2 Ruby Ruby 16384 Nov 9 08:18 1 16 drwx------ 2 Ruby Ruby 16384 Nov 9 08:18 14942 24 drwx------ 2 Ruby Ruby 20480 Nov 9 08:18 14948 20 drwx------ 2 Ruby Ruby 20480 Nov 9 08:18 16763 20 drwx------ 2 Ruby Ruby 20480 Nov 9 08:18 25211 20 drwx------ 2 Ruby Ruby 20480 Nov 9 08:18 25294 20 drwx------ 2 Ruby Ruby 20480 Nov 9 08:18 25295新建一个数据库gaussdb=> create database db_newdb; gaussdb=> select oid,datname from pg_database; oid | datname -------+------------ 1 | template1 14942 | template0 17325 | db_ora 17457 | db_conn10w 17458 | db_default 14948 | postgres 16809 | test 17521 | db_newdb很明显会发现多了33483这个目录,可是我新建这个db_newdb的oid是17521啊,为什么对不上呢?[Ruby@gauss-dis-133 base]$ ls -lsa total 160 4 drwx------ 10 Ruby Ruby 4096 Nov 9 14:29 . 4 drwx------ 22 Ruby Ruby 4096 Nov 9 14:51 .. 16 drwx------ 2 Ruby Ruby 16384 Nov 9 08:18 1 16 drwx------ 2 Ruby Ruby 16384 Nov 9 08:18 14942 24 drwx------ 2 Ruby Ruby 20480 Nov 9 08:18 14948 20 drwx------ 2 Ruby Ruby 20480 Nov 9 08:18 16763 20 drwx------ 2 Ruby Ruby 20480 Nov 9 08:18 25211 20 drwx------ 2 Ruby Ruby 20480 Nov 9 08:18 25294 20 drwx------ 2 Ruby Ruby 20480 Nov 9 08:18 25295 16 drwx------ 2 Ruby Ruby 16384 Nov 9 14:29 33483```
-
以下是我在三节点分布式gaussdb上面查询到的结果:### cn里面也有数据文件 [root@gauss-dis-134 cn]# du -sh base 123M base [root@gauss-dis-134 cn]# du -sh global 514M global ### dn的大小 [root@gauss-dis-134 dn_6002]# du -sh base 255M base [root@gauss-dis-134 dn_6002]# du -sh global 514M global我的问题是:这是在同一个机器上面,为什么在cn目录下面也有base、global这些文件(里面是数据文件) 官方文档的描述里面不是说,由datanode负责数据的存储,cn只负责协调吗?如果同一台机器,cn和dn都存一样的数据,不会浪费空间吗?
-
小数点前0不显示postgres=# select 0.1 as result; result -------- .1(1 row)小数点前0会省略,是因为数据库中存在一个隐形类型转换,在拼接的过程中小数自动转成字符类型,相当于调用了to_char函数,所以丢失小数点前面的0解决方法:使用to_char进行转换-- 数字转字符串格式select to_char(a, 'FM9990.00')"FM9990D00", to_char(a, '99.90')"99D90", to_char(a, 'FM90D99')"FM90D99", rtrim(to_char(a, 'FM999990D99'), to_char(0, 'D'))"FM999990D99" from ( select 50 a from dual union all select 50.57 from dual union all select 5.57 from dual union all select 0.35 from dual union all select 0.4 from dual) FM9990D00 | 99D90 | FM90D99 | FM999990D99 -----------+--------+---------+------------- 50.00 | 50.00 | 50. | 50 50.57 | 50.57 | 50.57 | 50.57 5.57 | 5.57 | 5.57 | 5.57 0.35 | .35 | 0.35 | 0.35 0.40 | .40 | 0.4 | 0.4四种常用格式对比:【FM9990.00】格式,皆满足;代码更简洁;与【rtrim(to_char(a, 'FM999990D99'), to_char(0, 'D'))"FM999990D99"】的区别整数是否保留小数。【99D90】格式,问题:小数位小于1,0则不显示。【FM90D99】格式,问题:小数位为0,则不显示。【rtrim(to_char(a, 'FM999990D99'), to_char(0, 'D'))"FM999990D99"】格式,缺点:代码过于复杂化。注:【9】在小数位,则表示转换为对应字符,如果没有则以0表示;在整数位,没有对应则不填充字符。to_char(123,'999D99')=123.00;to_char(123,'99999D9')=123.0;注意事项:对于0和9而言,如果格式的位数不如数字的位数多,会返回'#'。譬如to_char(12345,'9999')='#####' 。 【0】代表如果存在数字则显示数字,不存在则显示0,即占位符;to_char(0.34,'0D00')='0.34';to_char(1234,'9999D00')='1234.00';注意事项:这是一个强制的符号,对应位没有,则以'0'填充,这是9很大不同地方。【D】(ISO 小数位符号) '999D99' 这是"点号"的国际版本(ISO),作用等同于点号,也是只能出现一次,也可以直接用'.'。【FM】代表删除如果是因9带来的空格,则删除,小数点后的9。
上滑加载中
推荐直播
-
华为云码道 × 仓颉编程:工程化AI编码探索2026/05/27 周三 19:00-21:00
刘俊杰-华为云仓颉语言专家/李炎-华为云码道技术专家/王智鹏-OpenCangjie开源社区发起人
本场直播围绕华为云仓颉语言与华为云码道的深度结合,展示华为云智能编程从零基础到高效落地的完整生态能力。以华为云码道为引擎,仓颉语言为载体,带给大家日常提效、趣味创新到极速量产的开发体验。
回顾中
热门标签