本文為您介紹如何在Hologres中使用跨庫查詢數據以及相關的使用示例。
背景信息
Hologres從V1.1版本開始,支持在不同地域、不同實例和不同數據庫之間,通過創建外部表的方式查詢數據,操作方便簡單。Hologres兼容Postgres,通過外部表的方式跨庫查詢原理同Postgres,詳情請參見FDW。
使用限制
僅Hologres V1.1及以上版本支持跨庫查詢數據,如果您的實例是V1.1以下版本,請您使用自助升級或加入Hologres釘釘交流群反饋,詳情請參見如何獲取更多的在線支持?。
僅支持跨庫查詢Hologres V1.1及以上版本的實例,同時僅支持相同大版本的Hologres實例互相跨庫查詢,暫不支持跨大版本的實例間互相查詢,例如不支持V1.3版本的實例查詢V1.1版本的實例。
僅支持跨庫查詢Hologres內部表中的數據,不支持查詢Hologres外部表和Hologres的視圖View。
僅支持跨庫查詢Hologres分區父表,不支持查詢Hologres分區子表。
僅支持INT、BIGINT、DATE等基本數據類型,JSON等復雜數據類型不支持。
不支持對外表執行
UPDATE
、DELETE
及TRUNCATE
等命令。由于Hologres實例IP不固定,可能會受IP白名單限制,使用跨庫查詢功能時暫不建議配置IP白名單。
跨庫查詢
使用跨庫查詢功能的詳細操作步驟如下。
創建extension
在使用之前,需要Superuser在數據庫中執行以下語句創建extension。創建extension需要實例的Superuser執行,該操作針對整個數據庫生效,一個數據庫只需執行一次。
--創建extension CREATE EXTENSION hologres_fdw;
說明如需卸載extension請執行如下命令。
DROP EXTENSION hologres_fdw;
創建Server
創建extension成功后,執行以下語句創建Server,用于連接跨庫查詢的實例。
說明同一個數據庫,可以創建多個Server。
CREATE SERVER <server_name> FOREIGN DATA WRAPPER hologres_fdw OPTIONS ( host '<endpoint>', port '<port>', dbname '<dbname>' );
參數
說明
示例
server_name
Server的名稱,自定義設置。
holo_fdw_server
host
Hologres實例的經典網絡地址。您可以進入Hologres管理控制臺的實例詳情頁,從實例配置頁簽獲取經典網絡(內網)地址。
hgpostcn-cn-xxx-cn-hangzhou-internal.hologres.aliyuncs.com
port
Hologres實例的端口。您可以進入Hologres管理控制臺的實例詳情頁,從實例配置頁簽獲取實例端口。
80
dbname
需要跨庫查詢的源數據庫名稱。
testdb
創建用戶映射
創建完server之后,使用如下語句創建用戶映射,用于查詢數據,需要保證創建的用戶映射有對應的原數據查詢權限。
說明同一個數據庫,可以創建多個用戶映射。
CREATE USER MAPPING FOR <賬號uid> SERVER <server_name> OPTIONS ( access_id '<access_id>', access_key '<access_key>' );
參數
說明
server_name
Server的名稱,上一步驟自定義設置的名稱。
access_id
當前訪問賬號的AccessKey ID,您可以單擊RAM控制臺,獲取AccessKey ID。
access_key
當前訪問賬號的AccessKey Secret,您可以單擊RAM控制臺,獲取AccessKey Secret。
使用示例
--為當前用戶創建用戶映射 create user mapping for current_user server holo_fdw_server options ( access_id 'LTAI5txxx', access_key 'y8LUUyyy' ); --為RAM用戶123xxx創建用戶映射 create user mapping for "p4_123xxx" server holo_fdw_server options ( access_id 'LIlY5txxx', access_key 'KsjkXKyyy' ); --刪除用戶映射 Drop USER MAPPING for CURRENT_USER server holo_fdw_server; Drop USER MAPPING for "p4_123xxx" server holo_fdw_server;
創建外部表
創建外部表有兩種方式,分別如下。
(推薦)使用
IMPORT FOREIGN SCHEMA
語句創建外部表使用
IMPORT FOREIGN SCHEMA
語句創建外部表,操作更加簡單方便,SQL語句如下。IMPORT FOREIGN SCHEMA <holo_remote_schema> [{ LIMIT TO EXCEPT }| (remote_table [, ...])] FROM SERVER <server_name> INTO <holo_local_schema> [ OPTIONS ( OPTION 'values' [, ...])];
說明導入外部表元數據需要讀取較多外部數據庫元數據,建議通過LIMIT TO參數限制只導入需要的表,避免整庫導入,可以保障外部表創建效率。
參數
說明
示例
holo_remote_schema
要跨庫查詢的源表所在的schema名稱。
remote
remote_table
要跨庫查詢的源表名稱,外部表創建成功,將會在新的數據庫創建與源表同名的外部表。
lineitem
server_name
創建的Server的名稱。
holo_fdw_server
holo_local_schema
創建的外部表所在的Schema名稱。
local
OPTION 'values'
創建外部表時的沖突策略,參數包含如下內容。
import_collate:列是否包括collate配置,默認為true。
import_default:列是否包括default值,默認為false。
import_not_null:列是否包含not null約束,默認為true。
import_not_null 'true'
使用
CREATE FOREIGN TABLE
語句創建外部表SQL語句如下。
CREATE FOREIGN TABLE <local_table> ( col_name type, ...... )SERVER <server_name> OPTIONS (schema_name '<remote_schema_name>', table_name '<remote_table>');
參數
說明
示例
local_table
創建的外部表名稱。默認表放在public schema,若是有自定義schema,需要在表名前加schema名,為
schema.table
。public.lineitem
server_name
創建的Server的名稱。
holo_fdw_server
remote_schema_name
要跨庫查詢的源表所在的Schema名稱。
public
remote_table
要跨庫查詢的源表名稱。
holo_lineitem
查詢外部表數據
外部表創建完成后,可以直接查詢外部表數據實現跨庫查詢,SQL語句如下。
select * from <holo_local_table> limit 10;
(可選)數據導入內部表
若是想要實現跨庫、跨實例導入數據,或者外部表查詢性能不滿足預期,可以通過如下SQL語句,將數據導入至Hologres內部表。
說明在使用之前,需要先創建一張內部表用于接收數據,創建內部表請參見管理內部表。
insert into <holo_table> select * from <holo_local_table>;
其他相關操作
查詢Server。
您可以使用如下SQL查詢已經創建的Server。
SELECT s.srvname AS "Name", pg_catalog.pg_get_userbyid(s.srvowner) AS "Owner", f.fdwname AS "Foreign-data wrapper", pg_catalog.array_to_string(s.srvacl, E'\n') AS "Access privileges", s.srvtype AS "Type", s.srvversion AS "Version", CASE WHEN srvoptions IS NULL THEN '' ELSE '(' || pg_catalog.array_to_string(ARRAY ( SELECT pg_catalog.quote_ident(option_name) || ' ' || pg_catalog.quote_literal(option_value) FROM pg_catalog.pg_options_to_table(srvoptions)), ', ') || ')' END AS "FDW options", d.description AS "Description" FROM pg_catalog.pg_foreign_server s JOIN pg_catalog.pg_foreign_data_wrapper f ON f.oid = s.srvfdw LEFT JOIN pg_catalog.pg_description d ON d.classoid = s.tableoid AND d.objoid = s.oid AND d.objsubid = 0 WHERE f.fdwname = 'hologres_fdw';
查看用戶映射。
您可以使用如下SQL查詢已經創建的用戶映射。
SELECT um.srvname AS "Server", um.usename AS "User name", CASE WHEN umoptions IS NULL THEN '' ELSE '(' || pg_catalog.array_to_string(ARRAY ( SELECT pg_catalog.quote_ident(option_name) || ' ' || pg_catalog.quote_literal(option_value) FROM pg_catalog.pg_options_to_table(umoptions)), ', ') || ')' END AS "FDW options" FROM pg_catalog.pg_user_mappings um WHERE um.srvname != 'query_log_store_server';
刪除用戶映射。
您可以使用如下SQL刪除某個用戶映射。
DROP USER MAPPING FOR <賬號uid> SERVER <server_name>;
server_name為Server的名稱。
刪除Server。
您可以使用如下SQL刪除某個Server。
重要刪除Server前需要刪除相關的用戶映射和外部表。
DROP SERVER <server_name>;
server_name為Server的名稱。
使用示例
本小節為您介紹跨庫查詢數據使用示例前的預置配置以及三個相關的完整示例。
預置配置
在示例之前,需要在Hologres里面已準備好一個實例,以及創建好數據庫,以及準備好相關的內部表數據,具體內容如下。
實例相關配置
配置
說明
源Hologres實例ID
hgpostcn-cn-i7mxxxxxxxxx
源Hologres數據庫名稱
remote_db
源Hologres實例schema名稱
remote
源Hologres內部表名稱
lineitem
源Hologres分區父表名稱
holo_dwd_product_movie_basic_info
源Hologres內部表DDL
BEGIN; CREATE SCHEMA remote; CREATE TABLE "remote"."lineitem" ( "l_orderkey" int8 NOT NULL, "l_linenumber" int8 NOT NULL, "l_suppkey" int8 NOT NULL, "l_partkey" int8 NOT NULL, "l_quantity" int8 NOT NULL, "l_extendedprice" int8 NOT NULL, "l_discount" int8 NOT NULL, "l_tax" int8 NOT NULL, "l_returnflag" text NOT NULL, "l_linestatus" text NOT NULL, "l_shipdate" timestamptz NOT NULL, "l_commitdate" timestamptz NOT NULL, "l_receiptdate" timestamptz NOT NULL, "l_shipinstruct" text NOT NULL, "l_shipmode" text NOT NULL, "l_comment" text NOT NULL ); COMMIT;
源Hologres分區表DDL
-- 分區父表 BEGIN; CREATE TABLE "remote"."holo_dwd_product_movie_basic_info" ( "movie_name" text, "director" text, "scriptwriter" text, "area" text, "actors" text, "type" text, "movie_length" text, "movie_date" text, "movie_language" text, "imdb_url" text, "ds" text ) PARTITION BY LIST (ds); comment on column "remote"."holo_dwd_product_movie_basic_info"."movie_name" is '電影名稱'; comment on column "remote"."holo_dwd_product_movie_basic_info"."director" is '導演'; comment on column "remote"."holo_dwd_product_movie_basic_info"."scriptwriter" is '編劇'; comment on column "remote"."holo_dwd_product_movie_basic_info"."area" is '制片地區/國家'; comment on column "remote"."holo_dwd_product_movie_basic_info"."actors" is '主演'; comment on column "remote"."holo_dwd_product_movie_basic_info"."type" is '類型'; comment on column "remote"."holo_dwd_product_movie_basic_info"."movie_length" is '電影長度'; comment on column "remote"."holo_dwd_product_movie_basic_info"."movie_date" is '上映日期'; comment on column "remote"."holo_dwd_product_movie_basic_info"."movie_language" is '語言'; comment on column "remote"."holo_dwd_product_movie_basic_info"."imdb_url" is 'imdb號'; COMMIT; --創建20170122為分區的分區子表 CREATE TABLE IF NOT EXISTS "remote".holo_dwd_product_movie_basic_info_20170122 PARTITION OF "remote".holo_dwd_product_movie_basic_info FOR VALUES IN ('20170122');
示例1:跨庫查詢非分區表
說明以下所有代碼實例,需要在跨庫查詢的數據庫中執行。
-- superuser創建extension CREATE EXTENSION hologres_fdw; --superuser創建server CREATE SERVER holo_fdw_server FOREIGN DATA WRAPPER hologres_fdw OPTIONS ( host 'hgpostcn-cn-i7mxxxxxxxxx-cn-hangzhou-internal.hologres.aliyuncs.com', port '80', dbname 'remote_db' ); -- 為當前用戶創建授權映射 CREATE USER MAPPING FOR CURRENT_USER SERVER holo_fdw_server OPTIONS (access_id 'LTAIxxxxxx', access_key 'Trjgyyyyyyy'); --創建schema(使用fdw功能的實例,local這個schema是非必需創建,可以換成業務的schema) CREATE SCHEMA local; -- 創建外部表 IMPORT FOREIGN SCHEMA remote LIMIT to (lineitem) FROM SERVER holo_fdw_server INTO local OPTIONS ( import_not_null 'true' ); SELECT * FROM local.lineitem limit 10;
示例2:跨庫查詢分區表
CREATE EXTENSION hologres_fdw; CREATE SERVER holo_fdw_server FOREIGN DATA WRAPPER hologres_fdw OPTIONS ( host 'hgpostcn-cn-i7mxxxxxxxxx-cn-hangzhou-internal.hologres.aliyuncs.com', port '80', dbname 'remote_db' ); -- 為當前用戶創建授權映射 CREATE USER MAPPING FOR CURRENT_USER SERVER holo_fdw_server OPTIONS (access_id 'LTAIxxxxxx', access_key 'Trjgyyyyyyy'); -- 創建schema(使用fdw功能的實例,local這個schema是非必需創建,可以換成業務的schema) CREATE SCHEMA local; -- 切換至本地實例(使用fdw功能的實例) IMPORT FOREIGN SCHEMA remote LIMIT to (holo_dwd_product_movie_basic_info) FROM SERVER holo_fdw_server INTO local OPTIONS ( import_not_null 'true' ); -- 直接查全表數據 SELECT * FROM local.holo_dwd_product_movie_basic_info limit 10;
示例3:將外部表數據導入內部表
-- 創建schema(使用fdw功能的實例,local這個schema是非必需創建,可以換成業務的schema) CREATE SCHEMA local; -- 創建內部表 BEGIN; CREATE TABLE "local"."dwd_product_movie_basic_info" ( "movie_name" text, "director" text, "scriptwriter" text, "area" text, "actors" text, "type" text, "movie_length" text, "movie_date" text, "movie_language" text, "imdb_url" text, "ds" text ); COMMIT; --導入內部表 insert into local.dwd_product_movie_basic_info select * from local.holo_dwd_product_movie_basic_info;
常見報錯
創建Server時,推薦使用主實例作為被查詢實例。如果出現以下報錯場景,請參見解決方法。
報錯場景:使用只讀從實例作為被查詢實例出現類似如下報錯信息。
internal error: Failed to get available shards for query[xxxxx], please retry later.
解決方法:請在被查詢只讀從實例的主實例和跨庫查詢的發起端實例內執行如下SQL命令。
ALTER DATABASE <database> SET hg_experimental_enable_dml_read_replica=ON;