-
TD:Select 1024**3;DWS:Select 1024^3;
-
【操作步骤&问题现象】
-
全文检索(Text search)顾名思义,就是在给定的文档中查找指定模式(pattern)的过程。GaussDB(DWS)支持对表格中文本类型的字段及字段的组合做全文检索,找出能匹配给定模式的文本,并以用户期望的方式将匹配结果呈现出来。本文结合笔者的经验和思考,对GaussDB(DWS)的全文检索功能作简要介绍,希望能对读者有所帮助。 1. 预处理 在指定的文档中查找一个模式有很多种办法,例如可以用grep命令搜索一个正则表达式。理论上,对数据库中的文本字段也可以用类似grep的方式来检索模式,GaussDB(DWS)中就可以通过关键字“LIKE”或操作符“~”来匹配字符串。但这样做有很多问题。首先对每段文本都要扫描,效率比较低,难以衡量“匹配度”或“相关度”。而且只能机械地匹配字符串,缺少对语法语义的分析能力,例如对英语中的名词复数,动词的时态变换等难以自动地识别和匹配,对于由自然语言构成的文本无法获得令人满意的检索结果。 GaussDB(DWS)采用类似搜索引擎的方式来进行全文检索。首先对给定的文本和模式做预处理,包括从一段文本中提取出单词或词组,去掉对检索无用的停用词(stop word),对变形后的单词做标准化等等,使之变为适合检索的形式再作匹配。 GaussDB(DWS)中,原始的文档和搜索条件都用文本(text)表示,或者说,用字符串表示。经过预处理后的文档变为tsvector类型,通过函数to_tsvector来实现这一转换。例如,postgres=# select to_tsvector('a fat cat ate fat rats'); to_tsvector ----------------------------------- 'ate':4 'cat':3 'fat':2,5 'rat':6(1 row) 观察上面输出的tsvector类型,可以看到to_tsvector的效果:首先各个单词被摘取出来,其位置用整数标识出来,例如“fat”位于原始句子中的第2和第5个词的位置。此外,“a”这个词太常见了,几乎每个文档里都会出现,对于检索到有用的信息几乎没有帮助。套用香农理论,一个词出现的概率越大,其包含的信息量越小。像“a”,“the”这种单词几乎不携带任何信息,所以被当做停用词(stop word)去掉了。注意这并没有影响其他词的位置编号,“fat”的位置仍然是2和5,而不是1和4。另外,复数形式的“rats”被换成了单数形式“rat”。这个操作被称为标准化(Normalize),主要是针对西文中单词在不同语境中会发生的变形,去掉后缀保留词根的一种操作。其意义在于简化自然语言的检索,例如检索“rat”时可以将包含“rat”和“rats”的文档都检索出来。被标准化后得到的单词称为词位(lexeme),比如“rat”。而原始的单词被称为语言符号(token)。 将一个文档转换成tsvector形式有很多好处。例如,可以方便地创建索引,提高检索的速度和效率,当文档数量巨大时,通过索引来检索关键字比grep这种全文扫描匹配要快得多。再比如,可以对不同关键字按重要程度分配不同的权重,方便对检索结果进行排序,找出相关度最高的文档等等。 经过预处理后的检索条件被转换成tsquery类型,可通过to_tsquery函数实现。例如,postgres=# select to_tsquery('a & cats & rat'); to_tsquery --------------- 'cat' & 'rat'(1 row) 从上面的例子可以看到:跟to_tsvector类似,to_tsquery也会对输入文本做去掉停用词、标准化等操作,例如去掉了“a”,把“cats”变成“cat”等。输入的检索条件本身必须用与(&)、或(|)、非(!)操作符连接,例如下面的语句会报错postgres=# select to_tsquery('cats rat');ERROR: syntax error in tsquery: "cats rat"CONTEXT: referenced column: to_tsquery 但plainto_tsquery没有这个限制。plainto_tsquery会把输入的单词变成“与”条件:postgres=# select plainto_tsquery('cats rat'); plainto_tsquery----------------- 'cat' & 'rat'(1 row)postgres=# select plainto_tsquery('cats,rat'); plainto_tsquery----------------- 'cat' & 'rat'(1 row) 除了用函数之外,还可以用强制类型转换的方式将一个字符串转换成tsvector或tsquery类型,例如postgres=# select 'fat cats sat on a mat and ate a fat rat'::tsvector; tsvector ----------------------------------------------------- 'a' 'and' 'ate' 'cats' 'fat' 'mat' 'on' 'rat' 'sat'(1 row)postgres=# select 'a & fat & rats'::tsquery; tsquery ---------------------- 'a' & 'fat' & 'rats'(1 row) 跟函数的区别是强制类型转换不会去掉停用词,也不会作标准化,且对于tsvector类型不会记录词的位置。 2. 模式匹配 把输入文档和检索条件转换成tsvector和tsquery之后,就可以进行模式匹配了。GaussDB(DWS)中使用“@@”操作符来进行模式匹配,成功返回True,失败返回false。 例如创建如下表格,postgres=# create table post(postgres(# id bigint,postgres(# author name,postgres(# title text,postgres(# body text);CREATE TABLE-- insert some tuples 然后想检索body中含有“physics”或“math”的帖子标题,可以用如下的语句来查询:postgres=# select title from post where to_tsvector(body) @@ to_tsquery('physics | math'); title ----------------------------- The most popular math books 也可以将多个字段组合起来查询:postgres=# select title from post where to_tsvector(title || ' ' || body) @@ to_tsquery('physics | math'); title ----------------------------- The most popular math books(1 row) 注意不同的查询方式可能产生不同的结果。例如下面的匹配不成功,因为::tsquery没对检索条件做标准化,前面的tsvector里找不到“cats”这个词:postgres=# select to_tsvector('a fat cat ate fat rats') @@ 'cats & rat'::tsquery; ?column?---------- f(1 row) 而同样的文档和检索条件,下面的匹配能成功,因为to_tsquery会把“cats”变成“cat”:postgres=# select to_tsvector('a fat cat ate fat rats') @@ to_tsquery('cats & rat'); ?column?---------- t(1 row) 类似地,下面的匹配不成功,因为to_tsvector会把停用词a去掉:postgres=# select to_tsvector('a fat cat ate fat rats') @@ 'cat & rat & a'::tsquery; ?column?---------- f(1 row) 而下面的能成功,因为::tsvector保留了所有词:postgres=# select 'a fat cat ate fat rats'::tsvector @@ 'cat & rat & a'::tsquery; ?column?---------- f(1 row) 所以应根据需要选择合适的检索方式。 此外,@@操作符可以对输入的text做隐式类型转换,例如,postgres=# select title from post where body @@ 'physics | math'; title-------(0 rows) 准确来讲,text@@text相当于to_tsvector(text) @@ plainto_tsquery(text),因此上面的匹配不成功,因为plainto_tsquery会把或条件'physics | math'变成与条件'physic' & 'math'。使用时要格外小心。 3. 创建和使用索引 前文提到,逐个扫描表中的文本字段缓慢低效,而索引查找能够提高检索的速度和效率。GaussDB(DWS)支持用通用倒排索引GIN(Generalized Inverted Index)进行全文检索。GIN是搜索引擎中常用的一种索引,其主要原理是通过关键字反过来查找所在的文档,从而提高查询效率。可通过以下语句在text类型的字段上创建GIN索引:postgres=# create index post_body_idx_1 on post using gin(to_tsvector('english', body));CREATE INDEX 注意这里必须使用to_tsvector函数生成tsvector,不能使用强制或隐式类型转换。而且这里用到的to_tsvector函数比前一节多了一个参数’english’,这个参数是用来指定文本搜索配置(Text search Configuration)的。关于文本搜索配置将在下一节介绍。不同的配置计算出来的tsvector不同,生成的索引自然也不同,所以这里必须明确指定,而且在查询的时候只有配置和字段都与索引定义一致才能通过索引查找。例如下面的查询中,前一个可以通过post_body_idx_1来检索,后一个找不到对应的索引,只能通过全表扫描检索。postgres=# explain select title from post where to_tsvector('english', body) @@ to_tsquery('physics | math'); QUERY PLAN ----------------------------------------------------------------------------------------------------- id | operation | E-rows | E-width | E-costs ----+---------------------------------+--------+---------+--------- 1 | -> Streaming (type: GATHER) | 1 | 32 | 42.02 2 | -> Bitmap Heap Scan on post | 1 | 32 | 16.02 3 | -> Bitmap Index Scan | 1 | 0 | 12.00 postgres=# explain select title from post where to_tsvector('french', body) @@ to_tsquery('physics | math'); QUERY PLAN ---------------------------------------------------------------------------------------------- id | operation | E-rows | E-width | E-costs ----+------------------------------+--------+---------+------------------ 1 | -> Streaming (type: GATHER) | 1 | 32 | 1000000002360.50 2 | -> Seq Scan on post | 1 | 32 | 1000000002334.50 4. 全文检索配置(Text search Configuration) 这一节谈谈GaussDB(DWS)如何对文档做预处理,或者说,to_tsvector是如何工作的。 文档预处理大体上分如下三步进行:第一步,将文本中的单词或词组一个一个提取出来。这项工作由解析器(Parser)或称分词(Segmentation)器来进行。完成后文档变成一系列token。第二步,对上一步得到的token做标准化,包括依据指定的规则去掉前后缀,转换同义词,去掉停用词等等,从而得到一个个词位(lexeme)。这一步操作依据词典(Dictionary)来进行,也就是说,词典定义了标准化的规则。最后,记录各个词位的位置(和权重),从而得到tsvector。 从上面的描述可以看出,如果给定了解析器和词典,那么文档预处理的规则也就确定了。在GaussDB(DWS)中,这一整套文档预处理的规则称为全文检索配置(Text search Configuration)。全文检索配置决定了匹配的结果和质量。 如下图所示,一个全文检索配置由一个解析器和一组词典组成。输入文档首先被解析器分解成token,然后对每个token逐个词典查找,如果在某个词典中找到这个token,就按照该词典的规则对其做Normalize。有的词典做完Normalize后会将该token标记为“已处理”,这样后面的字典就不会再处理了。有的词典做完Normalize后将其输出为新的token交给后面的词典处理,这样的词典称为“过滤型”词典。 图1 文档预处理过程 配置使用的解析器在创建配置的时候指定,且不可修改,例如,postgres=# create text search configuration mytsconf (parser = default);CREATE TEXT SEARCH CONFIGURATION GaussDB(DWS)内置了4种解析器,目前不支持自定义解析器。postgres=# select prsname from pg_ts_parser; prsname ---------- default ngram pound zhparser(4 rows) 词典则通过ALTER TEXT SEARCH CONFIGURATION命令来指定,例如postgres=# alter text search configuration mytsconf add mapping for asciiword with english_stem,simple;ALTER TEXT SEARCH CONFIGURATION指定了mytsconf使用english_stem和simple这两种词典来对“asciiword”类型的token做标准化。 上面语句中的“asciiword”是一种token类型。解析器会对分解出的token做分类,不同的解析器分类方式不同,可通过ts_token_type函数查看。例如,‘default’解析器将token分为如下23种类型:postgres=# select * from ts_token_type('default'); tokid | alias | description -------+-----------------+------------------------------------------ 1 | asciiword | Word, all ASCII 2 | word | Word, all letters 3 | numword | Word, letters and digits 4 | email | Email address 5 | url | URL 6 | host | Host 7 | sfloat | Scientific notation 8 | version | Version number 9 | hword_numpart | Hyphenated word part, letters and digits 10 | hword_part | Hyphenated word part, all letters 11 | hword_asciipart | Hyphenated word part, all ASCII 12 | blank | Space symbols 13 | tag | XML tag 14 | protocol | Protocol head 15 | numhword | Hyphenated word, letters and digits 16 | asciihword | Hyphenated word, all ASCII 17 | hword | Hyphenated word, all letters 18 | url_path | URL path 19 | file | File or path name 20 | float | Decimal notation 21 | int | Signed integer 22 | uint | Unsigned integer 23 | entity | XML entity(23 rows) 当前数据库中已有的词典可以通过系统表pg_ts_dict查询。 如果指定了配置,系统会按照指定的配置对文档作预处理,如上一节创建GIN索引的命令。如果没指定配置,to_tsvector使用default_text_search_config变量指定的默认配置。postgres=# show default_text_search_config; -- 查看当前默认配置 default_text_search_config---------------------------- pg_catalog.english(1 row)postgres=# set default_text_search_config = mytsconf; -- 设置默认配置SETpostgres=# show default_text_search_config; default_text_search_config---------------------------- public.mytsconf(1 row)postgres=# reset default_text_search_config; -- 恢复默认配置RESETpostgres=# show default_text_search_config; default_text_search_config---------------------------- pg_catalog.english(1 row) 注意default_text_search_config是一个session级的变量,只在当前会话中有效。如果想让默认配置持久生效,可以修改postgresql.conf配置文件中的同名变量,如下图所示。修改后需要重启进程。总结 GaussDB(DWS)的全文检索模块提供了强大的文档搜索功能。相比于用“LIKE”关键字,或 “~”操作符的模式匹配,全文检索提供了较丰富的语义语法支持,能对自然语言文本做更加智能化的处理。配合恰当的索引,能够实现对文档的高效检索。 本文简要介绍了GaussDB(DWS)全文检索的原理和使用方法,关于解析器和词典的更详细的介绍,请看另一篇文章《GaussDB(DWS)全文检索之解析器和词典》(待完成)。
-
针对GaussDB A 集群是支持使用psql对接集群数据库的,当前想知道的是psql的客户端需要在哪获取?
-
【问题场景】某局点使用Spark的scala接口从hive往GaussDB(DWS)进行大批量数据导入的时候,必然出现下面的报错,导致数据导入任务失败数据导入脚本如下:scala> val df = spark.read.table("CTE_REP.TEST").limit(1000000).repartition(6).toDF() scala> df.write.mode("Overwrite").jdbc("jdbc:postgresql://10.60.178.127:25308/postgres", "CTE_REP.test", t1)同时客户确认,使用相同的程序从hive往PostgesSQL导入数据的时候没有出现此类异常【问题原因】使用Spark的scala接口进行抽数操作时,如果数据源端的表定义中字段的数据类型和数据目标端的表定义中对应字段的数据类型不匹配,scala代码逻辑在处理NULL值和非NULL值时可能会导致bind成不同的数据类型,JDBC逻辑冲突,导致导入任务失败。,具体到Spark的scala代码如下对于非null值,使用函数makeSetter绑定参数值对于null值,调用 getJdbcType来绑定null值从上面代码可以看到函数getJdbcType和makeSetter都有一个入参dialect,这里的dialect(方言,这里的意思是要写入的数据库,比如Oracle、PostgreSQL、db2、teredata等)跟底层参数值的bind逻辑强相关。而出问题的集群上使用GaussDB(DWS)的驱动为gsjdbc200.jar,不在Spark内部注册的dialect范围(当前Spark内置注册的dialect有db2、mysql、oracle、teredata、postgresql、SqlServer、Derby)内。当同一个batch的数据的某个字段同时出现了null值和非null值的时候,会导致同一个字段bind走进了两个代码分支,有可能bind了两个不同的数据类型,触发了PreparedStatement的两次parse(具体原因需要看jdbc源码,此处未深入走读),导致出现这个问题。当Spark不识别驱动对应的dialect时,getJdbcType底层调用为函数getCommonJDBCType, 而CLOB在驱动gsjdbc200.jar中又被识别为OID,从而导致发生如上现象对于db2、mysql、oracle、teredata、postgresql、SqlServer、Derby这几种Spark内置支持的几种dialect,Spark代码中进行了特殊处理,在某些场景下会规避此类问题,降低问题出现的概率。 Spark对于Oracle的特殊处理如下:Spark对于PostgreSQL的特殊处理如下: 【触发因素】针对上述分析,结合现网场景进行排查,确定现网场景下具体触发因素如下数据源端的hive中表test的字段 report_dt的数据类型是string数据目标端GaussDB(DWS)中表test的字段 report_dt的数据类型是timestamp同一个批次导入的数据中,表test的report_dt字段出现了NULL值和非NULL值GaussDB(DWS)使用的驱动包是gsjdbc200.jar,Spark识别连接的方言信息为gauss200 【处理建议】保证源端和目标端的表定义的字段顺序和数据类型一致或者使用PostgesSQL生态兼容的驱动gsjdbc4.jar 【附-GaussDB(DWS)驱动说明】GaussDB(DWS)提供gsjdbc4.jar和gsjdbc200.jar两个驱动,它们的区别在于 gsjdbc4.jar:与PostgreSQL保持兼容的驱动包,其中类名、类结构与PostgreSQL驱动完全一致 gsjdbc200.jar:如果同一JVM进程内需要同时访问PostgreSQL及GaussDB(DWS),请使用此驱动包。它的主类名为“com.huawei.gauss200.jdbc.Driver”(即将“org.postgresql”替换为“com.huawei.gauss200.jdbc”),数据库连接的URL前缀为“jdbc:gaussdb”,其余与gsjdbc4.jar相同
-
华为云TechWave全球技术峰会将于4月8日在深圳召开,峰会以“创新 ∙ 普惠”为主题,围绕分布式云、云原生、音视频、数据等热点话题,携手来自全球的IT精英、技术大咖、先锋企业、合作伙伴共话前沿技术,发布华为云最新产品和解决方案,分享行业最佳应用实践,探讨企业智能升级的成长之道。创新普惠,一路前行,我们诚挚邀请您的参与。详情点击:https://www.huaweicloud.com/about/techwave_global_summit.html
-
过去几年,数据仓库和数据湖方案在快速演进和弥补自身缺陷的同时,二者之间的边界也逐渐淡化。云原生的新一代数据架构不再遵循数据湖或数据仓库的单一经典架构,而是在一定程度上结合二者的优势重新构建。在云厂商和开源技术方案的共同推动之下,2021 年我们将会看到更多“湖仓一体”的实际落地案例。InfoQ 希望通过选题的方式对数据湖和数仓融合架构在不同企业的落地情况、实践过程、改进优化方案等内容进行呈现。本文将分享网易严选的数据湖建设过程和思考。业务背景 网易严选在 2017 年中开始搭建自己的大数据体系,如今该体系已经支撑了严选的商业分析、搜索、推荐、广告、供应链、风控、商品开发、品控等几乎所有的业务场景。数据是电商运转的生命线,随着业务发展对数据的依赖程度越来越高,我们发现原来的数仓建设方法论及相关技术存在着一些比较明显的问题:数据的运转效率比较低。几乎所有的数据应用都重度依赖数仓模型,数仓模型本身的研发与迭代成本比较高,生产速度赶不上需求速度,这就导致我们的创新想法落地、业务策略迭代等都会被按下暂停键。数据的运转效率拖慢了业务的迭代效率。所以提升数据运转效率是我们数据体系演进的重要命题。业务的快速迭代导致了我们基础数据 schema 的频繁变更,而每次数据 schema 变更,都是一次伤筋动骨。我们的数据平台需要提供更加灵活的能力来低成本支撑数据 schema 的变化。需要更可靠的准实时镜像表。 要解决这些问题,都需要对我们的数据架构进行持续的迭代。先来看看我们迭代前的数据架构。数据架构图 1 数据体系架构图 图 1 是网易严选的数据技术体系,跟大多数公司的大数据架构和应用场景一致。数据从业务系统产生,经过数据的传输及集成,再到数据和算法加工,最后为数据产品 /BI 分析 / 算法业务(推荐 / 搜索 / 广告 / 风控)等使用,对业务提供数据辅助决策或自动化决策的能力。 图中有两条重要的大数据 Pipeline,一个是数据仓库流程,另外一个是机器学习流程:数据仓库开发,事先定义数据结构,业务数据经过了清理、丰富和转换,结果通常用于报告和分析。机器学习流程,倾向于使用未加工的原始数据,通过特征提取和模型开发,用于模型在线推理。两者在数据的需求和处理上有很多的不同,但随着业务场景和技术发展,这两者有同样的需求:数据和模型开发过程中,批流计算和存储的融合,提升开发效率;更实时的数据和模型,给业务提供更及时的数据决策能力;更加灵活的数据 schema,以应对业务和模型的快速迭代;直接分析与处理原始数据的能力。现状 & 目标 图 3 是严选数据集成和入仓流程图,和绝大部分公司一样。对于 Binlog 数据,通过采集组件(Canal)把相应的 Binlog 同步到 Kafka,对于日志数据,通过 Flume 采集同步到 Kafka,同时会经过一个 DataHub-Hound 组件,也就是一个 Kafka2Hive 的任务程序把它导入到原始数据,再经过 Merge 任务,产出数仓底层 ODS 数据。图 2 数据流程图 图中的 raw data 其实算一个狭义的数据湖,只是受限于 HDFS 的存储特点,无法支持 update 操作,无法支持灵活的 shema 语义以及 ACID 的保证。 所以存在 merge 任务,主要基于历史数据,和流式同步的增量数据进行合并,生产 ODS 层的周期快照数据。这样的实现,对于 T+1 离线数仓数据来说是可以满足的需求的,但对于近实时的数据分析需求,尤其是数据量大的表,无法在分钟级别完成合并。 在引入新的技术和解决方案时,我们会从以下几个目标去评估和实施落地:解决问题,新的技术和解决方案对我们整个数据 / 算法体系有没有新的能力突破,方法体系有没有革新?引入一个新的技术是需要解决系统通用的场景问题,而不是部分场景的应用。提升效率,新的技术和解决方案对我们体系的运转效率有多少提升?降低成本,是否能够降低存储 / 计算 / 使用成本?稳定落地,如何保障在不影响现有业务的情况下,大规模落地新的技术和解决方案? 所以我们想要通过数据湖,并且在不引入额外的存储成本的情况下,提供更加实时的数据能力。一个数据入仓更实时,这样一方面可以减轻 T+1 数据计算的压力,另外一方面可以提供更加实时的数据访问,对于算法工程的场景来说,为实时模型训练提供更加实时的特征数据。图 3 数据湖架构数据湖是解法? 最近几年,数据湖概念及相关技术发展的很迅速。就像每一个时髦的技术名词,数据湖的概念也非常的混乱,很多基础设施都自称自己是数据湖解决方案。数据湖到底是什么,相关的技术包括哪些?这其实取决于我们要用它来解决什么具体的问题。从自己的需求出发,去寻求解决方案落地,这样才不容易在各类营销概念中迷失。数据湖 vs 数据仓库 数据湖优先的设计,能够有更高的灵活性。数据湖的数据存储形式和结构可以不预先定义,可以是结构化的,也可以是半结构化的。计算引擎可以根据不同的场景读写数据湖中存储的数据,这意味着我们在对数据进行分析和处理时能获取到数据全部的初始信息,使用也更灵活,高效。 而数据仓库优先的设计,能够做到更加规范化的数据管理。数据进入数据仓库前,通常预先定义 schema,数据开发需要预先根据业务进行建模,构建数据模型,用户通过数据服务接口或者计算引擎访问数据模型来获取干净和规范的数据。图 4 数据仓库 vs 数据湖 对数据湖和数据仓库的区别很多文章都有描述,二者有各自的优势和局限性,但并不是必须要二选一。数据湖的优势 我们对数据湖的特性和严选业务实际的场景,做了一些探讨和分析,形成了我们自己的理解。 最初接触数据湖概念时,相信国内的许多同行会跟我有类似的疑惑:Hadoop 存储和计算非结构化数据的能力一直都没有问题,为什么需要郑重其事地提出这样的理念? 这可能要从数仓的发展历史看起,大量的数据仓库实践其实是从关系型数据库开始的,从数据仓库的概念开始,就没有把非结构化数据(比如图像)考虑在内。因此,数据湖理念是对数仓的一个变革,而对国内许多从 Hadoop 技术栈成长起来的同学而言,数据湖其实是天然的事情。 但是,数据湖的相关理念和技术依然对于 Hadoop 生态的数仓理念和方法有比较大的变革:从特性角度来看:结构化 / 非结构化数据往往是区分数据仓库和数据湖的重要特征,但是在网易严选,我们对非结构化数据的分析需求并不强烈。对于日志类数据,我们还是会做一些清洗并将其结构化后存入数据湖。我们不应该教条的理解数据湖 RAW Data 的定义。原始日志经过清洗 / 结构化后,只要其包括的信息没有变化,它依然是 RAW Data。从使用角度来看:数据湖强调对原始数据的使用。灵活的使用数据湖数据,对严选的数据体系有两方面的价值:1)提升数据开发效率。当我们需要探索数据洞察业务机会的时候,往往需要给数据开发提数据模型建设需求。由于数据探索的不确定性和临时性,几乎不可能为了临时的频繁的数据探索去排期建设数仓模型。同时数据模型建设完毕后,模型本身的能力就决定了我们探索数据价值的上限。2)避免信息的丢失。数仓模型的建设往往是为了满足过去或者当前的业务需求,在模型的开发过程中,不可避免的丢失掉对当时认为价值不大的数据信息。但是,我们在构建机器学习模型或者探索数据的时候,往往需要更加充分的信息,而传统的数仓从根本上无法避免这个问题。数据湖方案能够很好地解决以上两个问题。从实时性角度来看:Delta/Iceberg/Huid 经常被宣传为数据湖解决方案。从我们的角度来看,这些技术很好的解决了数据湖 ACID 的问题,并且提供了较好的实时性。意味着我们可以通过这些技术以比较实时的方式提供可靠的原始数据访问能力给应用。在 Delta Lake 这类存储格式出现之前,严选也自己构建了类似的比较高实时性的原始数据访问方案,但由于缺乏 ACID 能力的支持,使得实际落地的时候往往可靠性不足。 Delta/Iceberg/Hudi 也往往被认为是批量一体的存储解决方案。批流一体跟数据湖的概念糅合在一起,给很多大数据行业的同学带来了困扰。我们用 Delta 技术来构建原始数据层,那么如果用 Delta 构建近实时的 DWD 层,是不是也是数据湖?在这里需要做一个概念上的澄清:数据湖关注的是对原始数据高效、灵活的处理,DWD 及其他数仓分层是充分设计的数据模型,它并不符合我们对数据湖的定义和需求。落地实践 数据湖的建设,从技术层面需要解决的是数据写入和读取,以及如何跟现有的大数据平台及**技术集成在一起。总结下来主要有以下几点内容:数据的存储,选择什么样的存储格式作为数据湖的存储引擎;数据的写入,也就是业务数据如何流向到数据湖存储;元数据管理,数据湖里的数据如何进行元数据的存储 / 管理 / 查询;数据的访问,也就是跟我们现有的计算引擎 /OLAP 引擎的集成。 首先,对于数据的存储,我们的数据主要以结构化的数据为主,同时文件存储系统也是单一的 HDFS。我们从 2019 年开始,最早关注的是 Delta,所以选择它作为了我们的存储格式。随着开源项目 Hudi 和 Iceberg 的发展,我们拥有了更多更灵活的选择。三个项目在 ACID/ 时间旅行 / 自动合并等功能的支持现状和规划都大同小异,有很多文章对其有详细的对比,这里就不展开赘诉了。比较大的区别是 Iceberg 跟计算引擎解绑,目前 Hudi 也在增加此特性。 由于 Iceberg 在早期没有支持 Row-level 的 delete 功能,这个对于我们数据集成的场景是必须的,所以我们选择的是 Delta 作为我们的解决方案并且落地。由于早期考虑到了多种存储格式的支持,所以做了逻辑封装和抽象,在 Iceberg 支持 row-level 的 delete 之后我们也完成了快速支持和集成。Iceberg 对 Flink 的支持,可以解决流计算引擎统一和应用场景的扩大,我们也在逐渐往其迁移。 对于数据的写入和访问主要是在计算引擎 Flink/Spark/Presto 等的集成,三个计算引擎生态建设都相对比较完善,这里不展开细说。 元数据管理这块,由于提前对统一元数据服务进行了抽象和实现,在接入数据湖之后,由统一元数据服务实现对表存储格式(Delta 及 Iceberg)定义和元数据的查询,这样多个平台或其它服务,能够快速的实现对数据湖的元数据管理。 完成计算引擎和基础服务的支持,用户即可在大数据平台,包括数据总线 / 流计算 / 离线开发平台 / 机器学习平台等对数据湖的数据进行访问和使用了。 同时,我们还需要考虑如何稳定可靠的应用到生产系统中。得益于我们的三大基础服务的建设,元数据服务 + 血缘服务 + 监控服务 。图 5 数据湖架构 如图 5 所示,元数据和血缘服务,提供的元数据的管理和全链路数据追踪,为我们分级灰度切换提供了有力的支持。而全链路的数据监控体系,包括任务粒度的监控和自动容错,以及消息级别的处理延迟 / 丢失 / 重复的探测,为我们 0 故障的上线和切换提供了有力的保障。 目前我们完成了数据湖建设的初步阶段,下面对于我们的一些落地场景应用和解决的问题展开介绍。数据集成 数据集成在大数据流程当中是非常重要的一环,相信很多公司都经历了几代的技术发展和迭代。图 6 数据集成 v1 严选在数据量非常小的时候,每天凌晨的时候业务 DB 的数据简单粗暴的全部 load 到数仓。但是随着业务的发展,对于数据量大的 DB 和表,全量 load 数据所花的时间,直接影响离线数仓数据的产出时间。 于是有了数据集成的 V2.0 方案,自研了增量 merge 的方案,把数据的传输变成了实时的同步,针对不同的应用场景提供不同的数据。 在凌晨的时候,基于 T+2 的快照和当天变更数据,生成 T+1 的快照数据,也就是我们离线数仓底层 ODS 数据,这样我们整个数据入仓的时间减少到一个小时了,大大提高了整个数据的产出效率图 7 数据集成 v2 为了满足一些更加实时的场景,merge 模块提供了短周期快照 10/30/60 分钟级别的快照数据来满足这样的场景。但是这个方案存在比较大的缺陷:实时性无法满足。尤其是数据量大的表,是无法满足分钟级别近实时的数据需求;以空间换时间,有大量的存储资源浪费;没有 ACID 的支持,更新期间并发数据访问短暂不可用。 随着 Delta/Iceberg/Hudi 这样开源的存储格式的发展,给数据集成方案提供了很好的优化支持,能够解决以上提到的 3 个问题。如图 8 中的 DataHund 框架在 delta 和 iceberg 的基础上进行封装开发,完成实时入湖的集成方案。图 8 数据集成 v3数仓建设 数据湖的数据,实时性更强,可靠性更高。除了能够提供近实时的数据分析,在此基础上可以构建我们 ODS 层的数据。如下图所示:图 10 目前已经完成了近实时的数据访问场景,也就是我们的分钟 / 小时数据访问的场景需求,解决上面所提到的 3 个问题:实时性。平均延迟在 1s 左右,对于大数据量的表同步延迟在分钟级;节省了 70% 的计算和存储资;有了 ACID 的支持,下游任务访问数据失败率减少为 0。特征工程 除了数据分析应用的场景,我们把数据湖也应用在了机器学习的场景中。特征工程在机器学习中起着至关重要的作用,特征的好坏直接会影响到算法的最终效果,算法工程师将离线特征于算法模型的训练,同时实时特征用于在线推理服务。 原来的特征处理流程,存在有两个比较大的问题:特征不一致,造成这个问题的原因有:1. 离线特征和实时特征的开发人员不是同一个;2 特征处理的引擎不一样。离线训练模型。离线特征用于模型训练。数据产出到生成样本再到模型训练和部署上线,延迟在 24h 以上。图 11 通过引入数据湖,我们优化了上述流程,解决了特征不一致和模型训练不实时的问题。特征的计算主要通过 Flink 任务进行处理,处理后写入 Redis 用于线上预测,再将处理后的特征 append 到特征表(Iceberg)中,使得整个模型训练都可以变得更加实时。图 12 下图是我们特征存储的模块架构图,因为我们有特征存储的抽象和实现,所以集成数据湖的访问相对还是比较容易的,统一的特征读写 SDK,对于上层的特征处理任务和离线训练任务都能够无感知的迁移和使用。 特征存储服务包括三个部分:一块是特征的管理;一块是特征的存储,屏蔽底层存储介质;另一个模块是特征的访问,数据开发工程师通过 FeatureStore 提供的 SDK,将处理好的特征写入 FeatureStore。图 13 特征存储架构未来规划 数据湖和数据仓库在数据生产和服务效率上有很大的差别。我们在第一阶段完成了初步的平台集成和建设,正在灰度阶段,支撑了 5 个任务。接下来的工作更有难度和挑战,我们会跟算法团队、BI 团队协作,为更关键的服务和分析提供数据湖能力。比如搜索、推荐、风控等对数据模型的迭代需要非常频繁的服务;再比如对业务进行探索与分析等,对数据的使用存在比较大的随机性的场景。随着更多复杂场景的落地,需要我们对计算和存储引擎本身去做进一步的优化。转载自AI前线,作者:左琴,策划:蔡芳芳 https://mp.weixin.qq.com/s/S2Gh5BXRpJ0i5BKyot_Dwg免责声明:转载文章版权归原作者所有。如涉及作品内容、版权等问题,请及时联系文章编辑!
-
通信库参数中关于pooler开关,enable_stateless_pooler_reuse参数默认值为off。将CN与DN的enable_stateless_pooler_reuse参数同步设置为on并重启集群后生效。当pooler复用开关打开时,CN与DN之间的连接可以进行复用,而不用新建连接,减少建连的资源开销。那既然可以减少建连的资源开销,为什么默认值却设置为off呢?这是出于什么因素的考虑?
-
【功能模块】系统表查询权限管理【操作步骤&问题现象】1、业务中有各种系统表查询场景,例如,查询表创建时间,表最后一次DDL时间,表清单,用户清单,数据库清单等等,需要查询pg_class,pgxc_node,pg_tables等系统表。2、需要创建一个只读用户,可以查询所有系统表及系统视图,但是不赋予增删改的权限。【截图信息】【日志信息】(可选,上传日志内容或者附件)
-
【功能模块】【操作步骤&问题现象】1、想问一下产品文档上面写着支持default解析器 为什么我实际操作不存在呢是不是sql语句写错了 这里报错不存在: 这样也可以 【截图信息】【日志信息】(可选,上传日志内容或者附件)
-
扩容问题分类扩容通常是在“初始化服务和实例”和数据重分布两个步骤报错,可通过查看后台日志排查分析。 日志分析步骤1、 如果是在“初始化服务和实例”步骤报错,则使用omm用户登录报错的新扩容节点,查看日志/var/log/Bigdata/mpp/scriptlog/postinstall.log,如果日志文件中没有内容“PreInstall cmd :execPython_preinstallMPP”,则表示扩容流程在FIM初始化阶段报错,排查FIM日志分析;2、 如果有则继续搜索日志中是否有错误“ PreInstall failed ”,如果能搜到说明配置新节点环境失败,根据日志上下文处理失败问题修复环境;3、 如果是扩容加节点失败,则使用omm用户登录第一个老节点,进入/var/log/Bigdata/mpp/scriptlog/目录下,查看gs_postinstall_*.log扩容日志文件,根据日志内容判断扩容失败原因。4、 如果重分布步骤失败,可登陆第一个老节点查看/var/log/Bigdata/mpp/scriptlog/目录下gs_postinstall_*.log扩容日志文件;如果日志显示是gs_redis报错,则登录集群第一个CN节点查看$GAUSSLOG/bin/gs_redis/目录下的gs_redis日志文件,搜索“failed”关键字获取具体的失败原因。 常见扩容问题1、 扩容(添加新节点)过程中因为断电、机器reboot、网络闪断导致扩容失败。· 修复硬件故障,确保GaussDB(DWS)集群所有机器网络连接正常;· 确保集群所有机器上没有扩容残留进程(gs_expand, gs_dump, gs_dumpall, gsql,gs_redis)。su - ommps ux |grep gs_expand |grep -v grep |awk '{print $2}' |xargs kill -9ps ux |grep gs_dump |grep -v grep |awk '{print $2}' |xargs kill -9ps ux |grep gsql |grep -v grep |awk '{print $2}' |xargs kill -9ps ux |grep gs_redis |grep -v grep |awk '{print $2}' |xargs kill -9· 在FI Manager页面上,点击扩容“重试”按钮重入扩容。2、扩容(添加新节点)过程中启动新集群失败而导致扩容失败。1、 以omm用户登录部署GaussDB(DWS)集群的任意一个节点,查看未启动的实例。source /opt/huawei/Bigdata/mppdb/.mppdbgs_profilecm_ctl query -Cvd2、 检查哪个实例状态不正常,是否由于实例端口号冲突导致启动失败。source /opt/huawei/Bigdata/mppdb/.mppdbgs_profilecd $GAUSSLOG/pg_log/异常实例日志目录grep -nr ‘Is another postmaster’ postgresql-*.log3、 扩容到元数据导入阶段,元数据导入失败,或者元数据导入耗时超过1小时未完成。· 查看CMS节点扩容OM日志,执行到Restoring new nodes这一步出现SQL失败,说明导入元数据失败。登陆任一新节点查看具体的sql失败信息:su - ommsource /opt/huawei/Bigdata/mppdb/.mppdbgs_profilecd $GAUSSLOG/om/ls -trl gs_local*.logtail -f gs_local*.log根据日志找到restore失败的SQL语句。分析失败原因,如果确认是SQL语法不支持,导入到新集群失败,需要先回退到老集群,然后删除或者修改不支持的SQL语法。记录不支持的SQL语句;在FI Manager界面上点击扩容“回退”按钮,回退到老集群;使用gsql客户端连接CN节点,删除或者修改不支持SQL语句。4、 扩容到元数据导出阶段,由于事务锁资源不足,导致元数据导出失败。· 以omm用户登录CMS主服务器节点。执行如下命令:source /opt/huawei/Bigdata/mppdb/.mppdbgs_profilegrep -nr "You might need to increase max_locks_per_transaction" $GAUSSLOG/bin/gs_dump/gs_dump -*-current.log若上述命令执行有结果输出,则说明GaussDB(DWS)集群中因事务锁不足导致扩容dump失败。· 获取GaussDB(DWS)的行存表、列存表、分区表、外表、索引、视图等数据库对象的数量。max_locks_per_transaction * (max_connections + max_prepared_transactions) 必须大于对象个数。在GaussDB(DWS)集群任意一个节点,参照如下命令,修改GUC参数配置:source /opt/huawei/Bigdata/mppdb/.mppdbgs_profilegs_guc set -Z coordinator -N all -I all -c 'max_connections = 1024' -c 'max_prepared_transactions = 1000' -c 'max_locks_per_transaction = 1024'gs_guc set -Z datanode -N all -I all -c 'max_connections = 3000' -c 'max_prepared_transactions = 1000' -c 'max_locks_per_transaction = 1024'cm_ctl stop && cm_ctl start如果元数据导出阶段耗时超过1小时未完成,在GaussDB(DWS)集群任意一个节点,通过如下方法查看dump进度:source /opt/huawei/Bigdata/mppdb/.mppdbgs_profilecd $GAUSSLOG/bin/gs_dumpall/grep -nr "objects have been dumped" gs_dumpall-*-current.log5、 后台下发执行扩容重分布命令失败· 如果失败日志中不存在’If you want to check the progress of redistribution, please check the log file on’内容,说明还未开始重分布,根据失败报错提示查询原因并处理,如果日志存在If you want to check the progress of redistribution, please check the log file on’内容,查看日志提示的对应节点上重分布日志gs_redis-XXX.log。· 查看gs_redis-XXX.log日志里面的错误信息,1)如果错误信息提示:memory is temporarily unavailable,修改重分布并发度,重试下发扩容重分布命令。2) 如果提示连接DN失败,检查对应DN的状态并修复,然后重试下发扩容重分布。3)如果提示出现磁盘损坏,修复磁盘,如果无法修复可以进行节点替换。本文转载于华为云数仓GaussDB(DWS)公众号
-
摘要:扩容问题定位指南(一)1 扩容基本原理1.1 扩容总体流程1. 用户在FIM界面提交扩容加节点请求;2. FIM向所有新节点下发命令,执行preinstall;3. 第一个新节点在完成preinstall之后等待所有新节点都已完成preinstall,然后ssh到第一个老节点调用gs_expand做内核扩容加节;其它新节点在...1 扩容基本原理1.1 扩容总体流程1. 用户在FIM界面提交扩容加节点请求;2. FIM向所有新节点下发命令,执行preinstall;3. 第一个新节点在完成preinstall之后等待所有新节点都已完成preinstall,然后ssh到第一个老节点调用gs_expand做内核扩容加节;其它新节点在完成preinstall之后直接退出;4. 新版本:用户在FIM界面提交数据重分布请求,经过内部转发,最终在第一个老节点调用重分布工具gs_expand进行数据重分布;老版本:用户在后台第一个cn节点直接调用gs_expand进行数据重分布;5. gs_expand在完成重分布前置准备工作之后ssh到第一个cn节点,调用该节点上gs_redis开始实际进行用户表的数据重分布1.2 日志路径mpp-postinstall.sh日志/var/log/Bigdata/mpp/scriptlog 所有节点均有gs_expand日志/var/log/Bigdata/mpp/scriptlog/postinstall-xxxx-xx-xx_xxxxx.log 第一个老节点/var/log/Bigdata/mpp/omm/om/gs_expand-xxxx-xx-xx.log 第一个老节点/var/log/Bigdata/mpp/scriptlog/gs_local-xxxx-xx-xx_xxxxx.log 所有节点均有gs_redis日志/var/log/Bigdata/mpp/omm/bin/gs_redis/gs_redis-xxxx.log 第一个cn节点1.3 扩容加节点1.3.1 元数据同步1、导出cn元数据命令gs_dumpall -p 25308 -s --include-nodes --dump-nodes --include-templatedb --include-buckets --include-alter-table --dump-wrm --non-lock-table --file='/opt/huawei/Bigdata/mppdb/mppdb_tmp/schema_coordinator.sql' --parallel-jobs 52、导出cn pg_job and pg_job_proc表数据gs_dump -p 25308 postgres -a --file='/opt/huawei/Bigdata/mppdb/mppdb_tmp/schema_coordinator_job_data.sql' -t pg_catalog.pg_job -t pg_catalog.pg_job_proc3、导出cn 统计信息/opt/huawei/Bigdata/mppdb/mppdb_tmp/schema_coordinator_statistics_data.sql4、导出dn全局元数据命令gs_dumpall -p 25330 -s --dump-wrm --include-templatedb --file='/opt/huawei/Bigdata/mppdb/mppdb_tmp/schema_datanode.sql' -g5、导出dn每个库元信息命令gs_dump -C -p 25330 dbname --include-alter-table --non-lock-table --file='/opt/huawei/Bigdata/mppdb/mppdb_tmp/dump_output_datanode_dbname.sql'6、导出元数据文件清单保存在临时目录/opt/huawei/Bigdata/mppdb/mppdb_tmp下:schema_coordinator.sql --cn全局元数据信息schema_coordinator_dbname.sql --cn上单个database的元数据信息,每个database一个schema_coordinator_job_data.sql --cn上的job信息schema_coordinator_statistics_data.sql --cn上的统计信息schema_datanode.sql --dn全局元数据信息dump_output_datanode_dbname.sql --dn上单个database的元数据信息,每个database一个1.4 数据重分布1.4.1 数据重分布监控在进入数据重分布阶段后,可同时打开多个连接到第一个cn节点的窗口,从如下维度对数据重分布进行全方位监控:1) 完成表数和剩余表数watch -n 3 "gsql -d postgres -p 25308 -c ' select * from redis_progress order by name;'"2) 活跃语句数及运行时长watch -n 3 "gsql -d postgres -p 25308 -c \"select application_name,pid,(current_timestamp - query_start) as runtime,query from pg_stat_activity where application_name='gs_redis' and state != 'idle' order by runtime desc;\""3) 新节点io选择一个新节点,执行如下命令监控ioiostat -xm 24) 老节点io选择一个老节点,执行如下命令监控ioiostat -xm 25) 重分布日志omm用户登录第一个cn节点,进入如下目录,cd /var/log/Bigdata/mpp/omm/bin/gs_redis找到最新的gs_redis开头的日志文件ls -lrt监控重分布日志tail -f gs_redis-xxxx.log1.4.2 查询有哪些表还未重分布重分布过程中或估算剩余时间窗是否足够时,需要查看还剩多少表未重分布,步骤如下:1、 找到老的nodegroup名称old_group_nameselect group_name from pgxc_group where in_redistribution='y';2、 分别连接每个database统计各个database下未重分布的表数量select count(*) from pgxc_class where pgroup='old_group_name';3、 如果想知道具体未重分布的表名称,可换成如下sql:select pcrelid::regclass from pgxc_class where pgroup='old_group_name'1.4.3 查看超过100G的未重分布的大表数据重分布过程中如果想查看还有多少超过100G的大表未重分布,可按如下步骤查询:找到老的nodegroup名称old_group_nameselect group_name from pgxc_group where in_redistribution='y';分别连接每个database统计多少张超100G大表未重分布select count(*) from pg_class c, pgxc_class pc where c.oid=pc.pcrelid and pc.pgroup='old_group_name' and c.relpages*8192/1024/1024>100;分别连接每个database列出超100G未重分布大表清单select pc.pcrelid::regclass from pg_class c, pgxc_class pc where c.oid=pc.pcrelid and pc.pgroup='old_group_name' and c.relpages*8192/1024/1024>100;注意:此处超100G大表是按统计信息估算。1.4.4 手动终止数据重分布数据重分布过程中出于调整并发、等各种原因,可能需要暂时终止重分布。具体步骤如下:1、omm用户登录第一个cn节点;2、找到gs_redis进程并将其kill -9 杀掉ps -ef |grep gs_redis|grep -v grep找到重分布进程pidkill -9 pid 杀掉重分布进程ps -ef |grep gs_redis|grep -v grep确认进程已被kill掉3、连接第一个cn,将数据重分布活跃语句全部终止掉SELECT pg_terminate_backend(pid)1.4.5 后台手动调用重分布命令1、omm用户登录第一个cn节点;2、调用重分布命令source /opt/huawei/Bigdata/mppdb/.mppdbgs_profilegs_expand -t redistribute --fast-redis --parallel-jobs=12 --redis-mode=read-onl1.4.6 跳过特定表数据重分布过程中由于有些用户表存在倾斜、数据文件损坏等各种原因,可能需要暂时跳过这些表,先完成其它表的重分布。跳过特定表的具体步骤如下:1、设置append_mode = offalter table pgxc_redistb set (append_mode = off);2、跳过指定表nspname.tb_nameselect * from pgxc_redistb where relname = 'tb_name' and nspname=’nspname’;update pgxc_redistb set redis_order = 0 where relname = 'tb_name' and nspname=’nspname’ and redistributed = 'n';3、恢复表为只读模式alter table pgxc_redistb set (append_mode = read_only);4、确认是否生效select redis_order from pgxc_redistb where relname = 'tb_name';tb_name的redis_order字段改为0,则说明已跳过该表。注意:跳过操作是暂时的,最终在完成其它表之后仍然需要完成这些跳过表的重分布,否则集群仍然处于重分布状态1.4.7 手动还原正在重分布表的append_mode重分布终止后,正在重分布的表无法自动设回append_mode=off,此时业务上如要对这些表执行插入操作将无法执行,需要先对这些表手动设置append_mode=off,方法如下:1、找到正在重分布的表select 'alter table '||a.nspname||'.'||b.relname||' set (append_mode = off);' from pg_namespace a, pg_class b where a.oid=b.relnamespace and b.reloptions::text like '%read_only%' and b.relname <> 'pgxc_redistb';2、修改append_modealter table table_name set (append_mode = off)本文转载于华为云数仓GaussDB(DWS)公众号
-
问题描述:某查询第一次执行时很慢,再次查询时速度正常。一部分执行计划如下:解决方法:该表是列存分区表,且分区数较多,分区表上的数据较少,小表没有必要使用分区,分区数过多的小表反而会增加分区扫描的开销,改成非分区表后查询速度正常。
-
问题现象:解决方法:将om_monitor中的报错信息中的目录移除后,重启集群,ETCD恢复,sequence能够正常创建。参考:https://blog.51cto.com/goome/2375348 https://www.codenong.com/cs106950407/
-
本文主要梳理了现网中同一条sql,普通用户比dbadmin用户执行的慢的情况,欢迎补充~场景一:普通用户在排队:waiting in queue/waiting in global queue/waiting in ccn queue说明:1. 普通用户主要在waiting in queue/waiting in global queue: 当前的活跃语句数超过max_active_statements限制导致的普通用户排队,由于管理员用户不受管控所以无需排队;可通过调大该参数或清理一部分语句规避; 2. 普通用户在waiting in ccn queue比较耗时,动态资源管理打开的情况下(enable_dynamic_workload = on),如果此时并发较高,可用内存比较少,普通用户执行语句时会进入该状态,管理员用户不受管控;可通过杀掉一部分语句或调大内存参数规避,如果各dn的内存使用都不高,也可考虑关闭动态资源管理enable_dynamic_workload场景二: 执行计划中的or条件中有权限相关的判断说明:此类场景多发生在使用系统视图时出现,例如如下sql:select distinct(dtp.table_name), ta.table_catalog, ta.table_schema, ta.table_name, ta.table_type from information_schema.tables ta left outer join DBA_TAB_PARTITIONS dtp on (dtp.schema = ta.table_schema and dtp.table_name = ta.table_name) where ta.table_schema = 'public';一部分执行计划如下:可以看到系统视图中的权限判断中多用or条件判断:pg_has_role(c.relowner, 'USAGE'::text) OR has_table_privilege(c.oid, 'SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER'::text) OR has_any_column_privilege(c.oid, 'SELECT, INSERT, UPDATE, REFERENCES'::text)由于dabadmin用户pg_has_role总能返回true,因此or之后的条件无需继续判断;而普通用户的or条件需要逐一判断,如果数据库中表个数比较多,最终会导致普通用户比dbadmin需要更长的执行时间。这种场景如果输出结果集很少,可以考虑尝试设置set enable_hashjoin = off; set enable_seqscan = off; 走index + nestloop的计划。场景三:普通用户和dbadmin所分配的资源池不同说明:select * from pg_user; 可以查看用户所对应的资源池是否相同,如果不同,可在界面查看两个资源池上所分配的租户资源是否有差别。
上滑加载中
推荐直播
-
华为云码道Agent集成与鸿蒙实战2026/08/11 周二 19:00-21:00
王一男-华为云码道产品规划专家;李炎-华为云码道产品专家;彭江敏-华为云鸿蒙端云一体化开发专家
本次直播带你解读华为云码道7月份产品新特性、新功能。更有专家演示码道Agent Space × 钉钉机器集成实战,从0到1打通消息通道;码道鸿蒙端云一体化实战,快速搭建员工签到系统。
回顾中 -
华为云开发者AI素养直播课·第五期2026/09/04 周五 16:00-18:00
林华鼎-华为云AI开发者运营负责人;蒋春阳-华为云AI开发者案例开发专家
本期直播内容: AI工具体验营 · 第5-8课连讲。Agent-Team 多智能体协作完成毕业设计实践
回顾中 -
华为云开发者AI素养ClassRoom·第六期2026/09/08 周二 19:00-20:00
樊渊-2026华为软件挑战赛冠军
高手来了:看软挑高手解析二维排样问题—从工业难题到算法突破
回顾中
热门标签