首页 文章 精选 留言 我的

精选列表

搜索[日活数],共10010篇文章
优秀的个人博客,低调大师

解密数仓的SQL ON ANYWHERE技术

本文分享自华为云社区《GaussDB DWS的SQL ON ANYWHERE技术解密》,作者:tooooooooooomy。 1. 前言 适用版本:【8.1.1(及以上)】 查询分析是大数据要解决的核心问题之一,虽然大数据相关的处理引擎组件种类繁多,并提供了丰富的接口供用户使用,但相对传统数据库用户来说,SQL语言依然是使用最简单、最广泛和方便的一种接口。如果能在一个客户端中使用SQL语句操作不同的大数据组件,将极大提升使用各种大数据组件的效率。 2. 什么是SQL On Anywhere GaussDB(DWS)的SQL On Anywhere,主要指对大数据的文件系统和与其他异构数据库的访问和交互,构筑起统一的大数据计算平台。大数据文件系统主要包括HDFS和OBS,其他异构数据库主要包括Oracle、Spark和Other GaussDB(DWS)。 3. GaussDB(DWS)SQL On Anywhere的作用及其应用场景 通过SQL On Anywhere特性可以实现与其他大数据组件和数据库互联互通访问,可以直接同时处理本地和HDFS/OBS上的数据集,甚至其他异构数据库的数据,而无需导入导出数据,将其分析能力从本地存储扩展到数据湖中,扩大GaussDB DWS的大数据分析的应用场景;通过该特性可以帮助客户实现冷热数据分离,将使用频度更高的热数据存储在本地,而使用频度更低的冷数据存储在成本更低廉的共享存储HDFS或者DWS上,降低用户成本。 从应用场景来看,可以满足如下业务需求: 针对多数据源需要构建虚拟的统一数据仓库,实现多数据源联邦查询,跨数据仓库热数据和HDFS/OBS冷数据的复杂混合查询,需要提供一致的、熟悉的数据仓库操作体验。 满足低频的业务全数据的低成本低延迟即席查询。 4. GaussDB(DWS)SQL On Anywhere的实现方式 GaussDB(DWS)SQL On Anywhere针对大数据的文件系统的访问主要通过FDW或ELK机制(已停止演进)实现的,而跨数据库的访问主要通过EC+ODBC的方式实现的。 3.1 利用FDW访问HDFS/OBS数据 GaussDB(DWS)对存储在HDFS上的Hadoop或者OBS原生数据的访问,采用FDW(Foreign Data Wrapper)机制,也称外表机制。首先通过创建Foreign Data Server来定义对HDFS数据源或同构其他集群的连接信息;之后创建Foreign Table,用于在GaussDB A数据库内部系统表中,定义对应的HDFS数据源上Hadoop原生结构化数据表的结构或对应同构其他集群结构化数据表的结构。 例如读取hdfs上的数据,其流程如下: ​ 1)建立一个hdfs_server,其中hdfs_fdw为数据库中存在的foreign data wrapper。 --创建hdfs_server。 postgres=# CREATE SERVER hdfs_server FOREIGN DATA WRAPPER HDFS_FDW OPTIONS (address '10.146.187.231:8000,10.180.157.130:8000' , hdfscfgpath '/opt/hadoop_client/HDFS/hadoop/etc/hadoop', type 'HDFS' ) ; ​ 2)创建一个hdfs外表读取hdfs上的数据 CREATE FOREIGN TABLE region ( R_REGIONKEY INT4, R_NAME TEXT, R_COMMENT TEXT ) SERVER hdfs_server OPTIONS( FORMAT 'orc', FOLDERNAME '/user/hive/warehouse/mppdb.db/region_orc11_64stripe/' ) DISTRIBUTE BY roundrobin; ​ 3)查询HDFS外表,例如: select * from region limit 10; 目前外表支持与普通表进行关联查询,并支持多种文件存储格式,其支持的文件格式如下(不同版本能力可能存在差异,以官方文档为准): 3.2 通过ELK访问HDFS(已停止演进,不推荐) ELK的方式类似于HAWQ,它是通过建立表空间为HDFS表空间,直接将数据存储和访问HDFS文件系统,目前只支持访问HDFS文件系统,而不支持访问OBS上的数据。首先通过创建HDFS表空间,然后会创建一个HDFS表,在创建时指定表空间为HDFS表空间,最后对HDFS表的操作如同普通表的操作,可进行插入修改删除数据。 以GaussDB数据库数据推到HDFS中 ​ 1)在数据库中创建HDFS表空间 CREATE TABLESPACE hdfs_table RELATIVE LOCATION ‘tmp/hdtest’ With (filesystem=’hdfs’, address=’28.4.136.221:9000’, cfgpath=’/opt/Huawei/bigdata/mppdb/hdfs_conf/zhndnrop/omm@HADOOP.COM/’, storepath=’/tmp/test’); ​ 2)数据库中创建HDFS表 CREATE TABLE abc( zjxxlh char(20), nbbsh char(20), khwybh char(20), zjlx char(20) )WITH (orientation=orc) TABLESPACE tables_hdfs; ​ 3)向表中插入数据 insert into abc select * from region10; 3.3 基于EC+ODBC的跨集群访问数据 GaussDB(DWS)支持通过 EC(全称Extension Connector)+ODBC统一访问其它大数据组件——将SQL发给其它大数据组件并接收执行结果,实现跨集群访问数据。目前EC+ODBC为用户提供了三种功能: SQL on Oracle、SQL on Spark和SQL on other GaussDB,分别用于连接Oracle数据库、Spark集群和其他GaussDB集群。 EC+ODBC的基本工作原理是:用户首先构建Data Source对象(其中包含目标库的一些连接信息和字符编码方式),然后用户获取该Data Source的使用权限,最后通过标准ODBC API连接目标库,发送SQL语句并获取执行结果。 为了方便使用,EC+ODBC为用户提供了统一的连接函数exec_on_extension(text, text)。其中,第一个参数为Data Source名称,第二个参数为发送的SQL语句,例如: postgres=# SELECT * FROM exec_on_extension('ds_spark', 'select * from a;') AS (c1 int); 5. GaussDB(DWS) SQL On Anywhere的实现方式优缺点对比 点击关注,第一时间了解华为云新鲜技术~

优秀的个人博客,低调大师

数仓如何递归查询视图依赖

本文分享自华为云社区《GaussDB(DWS)如何递归查询视图依赖》,作者:半岛里有个小铁盒。 1. 前言 适用版本:【8.1.0(及以上)】 本文通过介绍with recursive递归查询的办法来实现查询视图的层级依赖关系 2. 实现简介 对于postgres生态来说,视图的依赖关系没有现成的查询方法,需要对系统表pg_depend及pg_rewrite编写复杂的组合查询才能得知,而对于Oracle和MySql,该需求都较易实现,分别查询USER_DEPENDENCIES和INFORMATION_SCHEMA.VIEWS即可轻易查出,因此在pg生态来说有必要编写一个直观的视图来查看各个视图与基表或与其他视图的层级依赖关系。本文通过with recursive递归查询的办法来实现视图的层级依赖关系查询。效果如下: 首先建立两个基表t1、t2,表结构随意,再建立一系列的视图进行层级关联,关联关系也随意。本文的建表及视图语句如下: create table t1 (a int, b int) distribute by hash(a); create table t2 (a int, b int) distribute by hash(a); create view v1 as select * from t1; create view v2 as select * from v1; create view v3 as select * from v2; create view v4 as select * from v3; create view v5 as select * from t2; create view v6 as select * from v5; create view v7 as select * from v6; create view v8 as select * from v2; 实际的局点中,用户的视图依赖关系肯定要比这复杂得多,本文仅讲解原理。对于上述的视图依赖关系,可以通过如下查询得出: SELECT c.ev_class::regclass::varchar AS objname, pc.oid::regclass::varchar AS refobjname, pc.relkind AS relkind FROM pg_depend a,pg_depend b,pg_class pc,pg_rewrite c WHERE a.refclassid=1259 AND a.classid=2618 AND b.deptype='i' AND a.objid=b.objid AND a.classid=b.classid AND a.refclassid=b.refclassid AND a.refobjid<>b.refobjid AND pc.oid=a.refobjid AND c.oid=b.objid AND (a.objid>=16384 or a.refobjid>=16384) GROUP BY c.ev_class,pc.oid,pc.relkind ORDER BY relkind; 其中倒数第二行的16384表示过滤掉系统对象,relkind表示上级依赖对象的类型,r说明依赖于基表,v表示依赖另一个视图。其查询结果如下: 可见这种查询并不直观,只能通过肉眼分析得出递归的依赖关系,对用户并不友好。莫急,先将上述查询保存为视图,例如起名为PUBLIC.gs_view_dependency。接下来我们来学习一下with recursive语法的使用方法,从pg官网可以get到的知识是,WITH语句通常被称为通用表表达式(Common Table Expressions)或者CTEs。WITH语句作为一个辅助语句依附于主语句,WITH语句和主语句都可以是SELECT,INSERT,UPDATE,DELETE中的任何一种语句。WITH语句还可以通过增加RECURSIVE修饰符来引入它自己,从而实现递归: WITH RECURSIVE语句包含了两个部分: (非递归部分)non-recursive term,即上图中的union all前面的部分 (递归部分)recursive term,即上图中union all后面的部分 执行步骤如下: 执行non-recursive term。(如果使用的是union而非union all,则需对结果去重)其结果作为recursive term中对result的引用,同时将这部分结果放入临时的working table中 重复执行如下步骤,直到working table为空:用working table的内容替换递归的自引用,执行recursive term,(如果使用union而非union all,去除重复数据),并用该结果(如果使用union而非union all,则是去重后的结果)替换working table 因此,照葫芦画瓢,我们可以先给这个CTE查询起个名字,例如: WITH RECURSIVE get_view_dependency AS ( ... ) 然后,我们可以把非递归部分写成: SELECT a.objname, a.refobjname, a.refobjname path FROM PUBLIC.gs_view_dependency a where a.relkind = 'r' 因为查找到类型为’r’的基表的时候,递归就应该结束了。并且我们需要将refobjname组装成一条path来实现依赖路径的直观表示。因为是递归,所以我们需要不止一次的调用PUBLIC.gs_view_dependency,因此我们给它起个别名a。而递归的条件显而易见,应该是用refobjname来与objname做内关联,因此我们可以写作: INNER JOIN get_view_dependency cte ON b.refobjname=cte.objname 其中cte就用来指代上一次的递归查询结果,而递归的退出条件就应该是最开始写的类型为’r’的情况。其中b就应该是递归部分每次调用的PUBLIC.gs_view_dependency。而我们除了要查询objname和refobjname外,更重要的是要组成一个path,而path每个节点最好通过一个’->'来直观表示,因此递归部分我们就可以写成: SELECT b.objname, b.refobjname, cte.path ||' -> '|| b.refobjname path FROM PUBLIC.gs_view_dependency b INNER JOIN get_view_dependency cte ON b.refobjname=cte.objname 因此,整个CTE递归查询便可以写成: WITH RECURSIVE get_view_dependency AS ( SELECT a.objname, a.refobjname, a.refobjname path FROM PUBLIC.gs_view_dependency a where a.relkind = 'r' UNION ALL SELECT b.objname, b.refobjname, cte.path ||' -> '|| b.refobjname path FROM PUBLIC.gs_view_dependency b INNER JOIN get_view_dependency cte ON b.refobjname=cte.objname ) SELECT * FROM get_view_dependency; 为了方便以后的使用,我们可以给它起个名字保存起来,例如CREATE VIEW PUBLIC.gs_view_table_dependency AS …。效果就是文章开头所示那样,便大功告成。 3. 总结 在数据库中,查询视图是一种非常有用的工具,它可以帮助我们更好地组织和管理数据。然而,查询视图的层级依赖关系可能会让人感到困惑。本文将介绍一种通过 with recursive 递归查询的办法来实现查询视图的层级依赖关系的方法,希望对你有所帮助。 点击关注,第一时间了解华为云新鲜技术~

优秀的个人博客,低调大师

解密数仓高可用failover流程

摘要: Gaussdb的HA采用主备从的架构实现数据可靠性。当主DN发生故障时,备DN走failover流程,升级成为新主DN,保证集群不因单DN故障而中断业务。 本文分享自华为云社区《【玩转PB级数仓GaussDB(DWS)】dws高可用之failover流程大解密》,作者:fxy0224。 众所周知,PostgreSQL通过WAL预写xlog日志的机制解决了在单机环境上因进程故障退出导致数据丢失的问题。但在磁盘损坏等情况下,存储在持久性介质的数据就会丢失无法恢复,因此通常采用多副本的方式来保证数据可恢复。在Gaussdb中采用了主备从架构保证数据可靠性。 在Gaussdb主备从架构下,主DN分别与备​DN、从备DN建连。正常情况下,主DN与备DN、从备DN均建立流复制通道,分wal同步和数据页同步两个通道。wal同步是将存储在磁盘中的wal文件读出,然后通过walsender线程发送到备DN;数据页同步是在列存或者批量导入行存数据的场景下使用,通过datasender线程将数据发送到备DN。备DN上通过walreceiver、datareceiver线程接收从主DN同步过来的数据。备DN对同步来的xlog做redo的方式实现与主DN的数据一致性。 failover的场景大致如下:当发生主DN故障且退出后,CM会向备DN通知failover升主的信号。备DN会率先主动连从备DN,将从备DN上的xlog与数据页同步至备DN。然后备DN升主,备DN和从备DN之间建立新的流复制通道。这样当主DN故障时,依靠备DN与从备DN,Gaussdb仍可对外提供服务。 failover时主备DN的状态变化过程如下: DN状态切换过程示意图 (由于wal机制,因此主备DN在启动时均先执行redo,redo完成后DN状态才从starting——>Normal) 当主DN因故障退出时,其状态显示为down。此时备DN处于断连状态,状态由standby Normal变为needrepair(disconnected),当备DN收到failover信号时,状态变为promoting,表示备DN正处于升主过程中。备DN状态变为primary Normal后,表示备DN升主成功。 failover时备DN的流程示意图如下: failover流程示意图 Gaussdb内部通过gs_ctl的方式发送给备DN的failover命令: gs_ctl failover [-w] [-t SECS] [-D DATADIR] [-U USERNAME] [-P PASSWORD],具体流程如下: 备DN上Postmaster线程将failover信号通知到Startup线程, startup线程收到failover信号后,将与主DN不断建连的datareceiver和walreceiver线程shutdown; startup线程获取连接从备的建连信息(从备DN的ip+port),然后通知Postmaster线程创建新的walreceiver和datareceiver线程。 备DN的walreceiver和datareceiver线程与从备DN的walsender和datasender建连。从备DN发送xlog日志与数据页信息到备DN 备DN将从备DN上的数据同步结束后,其walreceiver线程和datareceiver线程均退出。备DN由startup线程进行redo。redo完成后,备DN将创建walsender和datasender线程,并与从备DN的walreceiver和datareceiver线程分别建连,备DN升主成功。备DN升主后,新主将与CN连接,并将xlog日志与数据页文件同步至从备。 点击关注,第一时间了解华为云新鲜技术~

优秀的个人博客,低调大师

LeetCode 1:两数之和 Two Sum

题目: 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。 Given an array of integers, return indices of the two numbers such that they add up to a specific target. You may assume that each input would have exactly one solution, and you may not use the same element twice. 示例: 给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1] 解题思路: 暴力穷举:外循环遍历每个元素 x,内循环查找是否存在一个值与 target - x 相等的目标元素,返回相等的目标元素和 x 的索引。时间复杂度 O (n^2),效率太低,pass。 哈希表:哈希映射(map、dict),key 保存该元素,value 保存该元素索引。 两次遍历法:第一次遍历把所有元素及其索引保存到哈希映射,第二次遍历查找 target - x 相等的目标元素 一次遍历法:假如 y = target - x,则 x = target -y,所以一次遍历 在存入哈希映射的同时查找是否存在一个值与 target - x 相等的目标元素。 例:nums = [2, 11, 7, 15], target = 9, hashmap = { } 遍历: i = 0: target - x = 9 - 2 = 7, 7 不存在于 hashmap 中,则 x(2) 加入 hashmap, hashmap = {2 : 0} i = 1: target - x = 9 - 11 = -2, -2 不存在于 hashmap 中,则 x(-2) 加入 hashmap, hashmap = {2 : 0, 11 : 1} i = 2: target - x = 9 - 7 = 2, 2 存在于 hashmap 中,则返回列表 [2, 0] 代码: 两次遍历(Java): class Solution { public int[] twoSum(int[] nums, int target) { Map<Integer, Integer> map = new HashMap<>(); for (int i = 0; i < nums.length; i++) {//一次遍历转换成键值对,key为元素值,value为索引值 map.put(nums[i], i); } for (int i = 0; i < nums.length; i++) {//二次遍历查找符合条件的元素 int res = target - nums[i]; if (map.containsKey(res) && map.get(res) != i) {//查找到的目标元素不能为其本身 return new int[]{i, map.get(res)}; } } return null; } } 一次遍历 (Java): class Solution { public int[] twoSum(int[] nums, int target) { Map<Integer, Integer> map = new HashMap<>(); for (int i = 0; i < nums.length; i++) { int res = target - nums[i]; if (map.containsKey(res)) {//因为自身元素还未加入到 hashmap,无需 map.get(res) != i 条件判断 return new int[]{i, map.get(res)}; } map.put(nums[i], i);//未找到目标元素则将其加入 hashmap } return null; } } 一次遍历 (Python): class Solution: def twoSum(self, nums: List[int], target: int) -> List[int]: dic = {} for i, num in enumerate(nums): #枚举 nums 数组 if num in dic: return [dic[num], i] else: dic[target-num] = i 利用 Python 数组自带 index 方法解题: class Solution: def twoSum(self, nums: List[int], target: int) -> List[int]: for i, num in enumerate(nums): if target-num in nums and nums.index(target-num) != i: return [i, nums.index(target-num)] list.index(): 描述: index () 函数用于从列表中找出某个值第一个匹配项的索引位置。 语法: index () 方法语法: list.index(x, start, end) 参数: x-- 查找的对象。 start-- 可选,查找的起始位置。 end-- 可选,查找的结束位置。 返回: 该方法返回查找对象的索引位置,如果没有找到对象则抛出异常。 欢迎关注微.信.公.众号: 爱写Bug

优秀的个人博客,低调大师

LeetCode第1题:两数之和

题目 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。 示例:输入: nums = [2, 7, 11, 15], target = 9 解释: 因为nums[0] + nums[1] = 2 + 7 = 9 输出: [0, 1] 代码 class Solution(object): def twoSum(self, nums, target): """ :type nums: List[int] :type target: int :rtype: List[int] """ d = {} for i in range(len(nums)): if d.get(target - nums[i], None) == None: d[nums[i]] = i else: return (d[target - nums[i]], i) 本文链接:时光不写博客-Two Sum

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册