[关闭]
@lsmn 2015-11-04T06:54:22.000000Z 字数 5075 阅读 2614

利用外部数据封装器打破数据筒仓

数据库 NoSQL PostgreSQL MongoDB


摘要

作者Lenley Hensarling探讨了Postgre数据库的外部数据封装器(FDW)。FDW提供了一个SQL接口,用于访问远程数据存储中的数据对象。借助该接口,可以从像NoSQL数据库这样的、完全不同的数据源中集成数据,将它们存入一种公用模型。

正文

数字革命对数据管理系统造成了巨大的破坏。数据的急剧增长,企业存储、管理和理解他们收集的数据比以往任何时候都困难。与此同时,随着数据日益多样化,企业不仅要管理来自不断发展的连接性设备网络的大量结构化数据,还要管理半结构化和非结构化数据。

因此,就需要能够支持多种数据类型的解决方案。这一需求将传统的数据中心转变成了可以高效处理各种大数据的数据管理技术的混合体。这些技术包括关系型数据库、独立的NoSQL解决方案和专门处理地理空间数据的扩展,这里就不一一列举了。实际上,Dell最近研究发现,数据库管理员所负责的基础设施比以往任何时候都复杂,其中有72%的人表示他们必须支持的数据库数量正在增加。调查还发现,80%的受访者说他们必须支持多个应用,45%的受访者说他们必须支持多个用户组,而72%的受访者说他们的岗位职责总体上不断增加。

与此同时,为了加速应用程序交付及更加直接地响应业务线的需求,开发人员面临的压力也在增加。这就导致了“阴影IT(Shadow IT)”工作——这个术语用于描述在没有IT领导参与的情况下在组织内构建或使用的IT系统和解决方案。许多开发人员已经转向了NoSQL-only数据库解决方案。但是,使用这些技术为新的、专门的应用程序创建本地或异地集群,供它们分析来自社交媒体、移动或应用程序等各种使用图片或图形的数据源的、新的非结构化数据,会引入数据筒仓——使整个数据环境比以往任何时候都更难理解。另外,对企业而言,这也使数据管理更加困难,而且长期来看,更难保证数据的完整性。

在Postgres中集成“外部数据类型(Foreign Data Types)”

Postgres有一个针对这一难题的解决方案:一个名为“外部数据封装器(Foreign Data Wrapper,FDW)”的特性。该特性最初由PostgreSQL社区领袖Dave Page四年前根据SQL标准SQL/MED(SQL Management of External Data)开发。FDW提供了一个SQL接口,用于访问远程数据存储中的远程大数据对象,使DBA可以整合来自不相关数据源的数据,将它们存入Postgres数据库中的一个公共模型。

这样,DBA就可以访问和操作其它系统管理的数据,就像在本地Postgres表中一样。例如,使用FDW for MongoDB,数据库管理员可以查询来自文档数据库的数据,并使用SQL将它与来自本地Postgres表的数据相关联。借助这种方法,用户可以将数据作为行、列或JSON文档进行查看、排序和分组。他们甚至可以直接从Postgres向源文档数据库写入(插入、更细或删除)数据,就像一个一体的无缝部署。也可以对Hadoop集群或MySQL部署做同样的事。FDW使Postgres可以充当企业的中央联合数据库或“Hub”。

基于这些功能,FDW可以减轻与管理NoSQL解决方案所导致的各种数据筒仓相关的痛苦。首先,如果不恰当地处理(许多都没有)使用NoSQL-only解决方案的应用程序,就会损害企业数据的长期价值。按Gartner报告的说法,“由于没有运用信息治理策略和规划,到2017年,存储在NoSQL DBMS中的数据,50%都是对企业有害的。”[i]

Postgres FDW可以帮助DBA和开发人员保证数据完整性,提高开发人员效率,扩展现有资源的价值。

保证数据完整性

NoSQL-only数据库不遵从ACID;因此,跨数据集实现健壮的数据完整性(企业通常都需要他们的数据集具有完整性)就需要复杂的应用程序开发。此外,由于NoSQL-only解决方案只存储数据而不处理数据,所以数据必须交由应用程序分析。这意味着,应用程序(及每个应用程序开发人员)负责高效地访问数据、实现业务规则以及保持数据一致性——这降低了系统之间的一致性,增加了DBA将数据部署到应用程序的复杂度。

而且,每一种NoSQL数据库产品都使用一种不同的数据表示方式和数据访问/操作语言,这进一步增加了复杂度,这也是为什么组织可能会发现他们使用了多种互不兼容的NoSQL解决方案。这样,就不得不将数据处理从数据库中拿出来放在应用程序中——尤其是在缺少ACID遵从性的情况下——这可能会有问题,因为:

提高开发人员的生产力

现如今,开发人员有能力重用代码及开发存储过程,提升了开发速度,开发过程仅需几天,而不是数周。然而,NoSQL-only解决方案不支持存储过程,而且,由于它们并不代表一种单一的技术,所以它们抑制了重用代码、建立标准和发现人才的能力。Postgres FDWs可以在以下三个方面简化开发人员的工作:

新解决方案带来了好处,但同时也带来了挑战,需要新的技能集、维护规定、操作过程及部署、优化、升级要求。在应用程序部署时使用NoSQL-only解决方案可能会帮助开发人员快速交付,但在整体环境以及企业的数据策略方面的成本会很高。Postgres FDWs使组织可以在一个统一的平台上综合运用企业级关系型数据库和NoSQL能力来达到利用现有数据部署的目的。将互不相干的潜在筒仓数据源整合在一起,FDWs使IT部门对信息、商品、服务、利益相关人或信息描述的其它物品有一个全面的、整体的认识。这样,企业就能获得更多的信息,做出更明智的决策和推介,实现业务目标,推动战略计划。

MongoDB FDW实战

鉴于MongoDB的普及性,FDW for MongoDB的升级版本已经创建完成。该版本加入了PostgreSQL 9.3增强功能中新增的WRITE功能。最初,FDWs仅支持读取功能。借助扩展工具以及EDB针对FDW性能提升和数据稳定性所进行的开发,开发人员很容易使用简单的SQL语句(SELECT/INSERT/UPDATE/DELETE)操作MongoDB中的数据。

点击这里,可以从GitHub库中下载FDW。

下面是一些使用mongo_fdw的例子及MongoDB等效语句。

-- 安装完成后首次加载扩展
CREATE EXTENSION mongo_fdw;

-- 创建服务器对象
CREATE SERVER mongo_server FOREIGN DATA WRAPPER mongo_fdw OPTIONS (address '127.0.0.1', port '27017');

-- 创建用户映射
CREATE USER MAPPING FOR Postgres SERVER mongo_server OPTIONS (username 'mongo_user', password 'mongo_pass');

-- 创建外表 (注意:表的第1列必须是类型为“NAME”的“_id”。)
CREATE FOREIGN TABLE warehouse( warehouse_id int, warehouse_name text, warehouse_created timestamptz) SERVER mongo_server OPTIONS (database 'db', collection 'warehouse');

-- 在表中查找行
SELECT * FROM warehouse WHERE warehouse_id = 1; _id          | warehouse_id | warehouse_name | warehouse_created ------------------------+----------------+--------------------------- 53720b1904864dc1f5a571a0|            1 | UPS            | 12-DEC-14
12:12:10 +05:00

-- MongoDB中相应的查找语句
db.warehouse.find({"warehouse_id" : 1}).pretty() { "_id" : ObjectId("53720b1904864dc1f5a571a0"), "warehouse_id" : 1, "warehouse_name" : "UPS", "warehouse_created" : ISODate("2014-12-12T07:12:10Z") }

-- 向表插入行
INSERT INTO warehouse values (0, 1, 'UPS', to_date('2014-12-12T07:12:10Z'));

-- MongoDB中相应的插入语句
db.warehouse.insert ( { "warehouse_id" : NumberInt(1), "warehouse_name" : "UPS", "warehouse_created" : ISODate("2014-12-12T07:12:10Z") })

-- 从表中删除行
DELETE FROM warehouse where warehouse_id = 3;

-- MongoDB中相应的删除语句
db.warehouse.remove( { "warehouse_id" : 3 })

-- 更新表的一行数据
UPDATE warehouse set warehouse_name = 'UPS_NEW' where warehouse_id = 1;

-- MongoDB中相应的更新语句
db.warehouse.update ( {       "warehouse_id" : 1    }, { "warehouse_id" : 1, "warehouse_name" : "UPS_NEW" } )

-- 解释表
EXPLAIN SELECT * FROM warehouse WHERE warehouse_id = 1; QUERY PLAN ----------------------------------------------------------------- Foreign Scan on warehouse  (cost=0.00..0.00 rows=1000 width=44) Filter: (warehouse_id = 1) Foreign Namespace: db.warehouse b.warehousedwarehousems (4 rows)

-- 收集数据分布统计
ANALYZE warehouse;

本文包含的实例代码是由EnterpriseDB数据库架构师Ibrar Ahmed编写的。

关于作者

Lenley Hensarling目前是EnterpriseDB战略和产品管理部门的副总裁。他的主要职责是在产品开发过程中确定战略方向以及同客户与合作伙伴交流。Lenley在大型企业技术组织中积累了20多年的软件行业经验。他曾在J.D. Edwards作过很长时间的主管,之后又先后在PeopleSoft和Oracle担任领导角色。在Novell,他最初是名工程技术人员,但很快就升职为工程部门的副总裁。Lenley在德克萨斯州大学奥斯汀分校获得了经济学学士学位。
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注