Chinaunix首页 | 论坛 | 博客
  • 博客访问: 129559
  • 博文数量: 19
  • 博客积分: 35
  • 博客等级: 民兵
  • 技术积分: 100
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-26 15:45
文章分类

全部博文(19)

文章存档

2016年(4)

2015年(13)

2014年(1)

2011年(1)

我的朋友

分类: Mysql/postgreSQL

2016-01-15 18:36:15

FDW Foreign Data Wrapper
用于通过PG访问外部表
1. 通过cretae server 关联 ip port dbname
2. 通过cretae user mapping 关联 user password
3. 通过 create foreign table 关联外部表在本地的映射,只保存元信息在本地,数据保存在远程表中
4. 本地数据库到远程数据库的链接,就是通过server 和 user mapping 建立的,必要的信息包括:ip,端口,用户,密码,数据库名

查询一个 foreign table 的流程如下;
1. 通过本地的元信息构造表的结构,列的数据类型,属性等
2. 构造优化器节点 create foreign scan 时,根据用户输入内容,构造 sql 语句,如 select a,b from t
最终的优化器节点内保存了获取远程数据库数据的sql语句。
优化器估算外部表的大小时,可以选择使用远程的数据库的信息,通过create server 时指定参数 use_remote_estimate 来设定
当选择了使用远程数据库统计信息时,优化器会连接远程数据库执行 explain ,获取返回的统计信息,包括
cost [startup..total], rows, width 一共4个值;
explain 结果类似下面这样,结果就是 startup=0.00, total=13.10 rows=310, width=230
Seq Scan on t1  (cost=0.00..13.10 rows=310 width=230)

3. 执行器初始化阶段,建立与远程数据库的链接,设置属性的输出函数,构造结构体
4. 执行器执行阶段,调用 ExecForeignScan -> ForeignNext 向远程数据库取数据,通游标的方式获取。
   执行器每次获取100条数据,缓存起来,这100用完,继续 fetch;直到取完全部数据或遇到 limit 提前结束。
贴一段代码:
通过cursor每次fetch 100 条的操作就在  fetch_more_data 中做的

点击(此处)折叠或打开

  1. static TupleTableSlot *
  2. postgresIterateForeignScan(ForeignScanState *node)
  3. {
  4.     PgFdwScanState *fsstate = (PgFdwScanState *) node->fdw_state;
  5.     TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;

  6.     /*
  7.      * If this is the first call after Begin or ReScan, we need to create the
  8.      * cursor on the remote side.
  9.      */
  10.     if (!fsstate->cursor_exists)
  11.         create_cursor(node);

  12.     /*
  13.      * Get some more tuples, if we've run out.
  14.      */
  15.     if (fsstate->next_tuple >= fsstate->num_tuples)
  16.     {
  17.         /* No point in another fetch if we already detected EOF, though. */
  18.         if (!fsstate->eof_reached)
  19.             fetch_more_data(node);
  20.         /* If we didn't get any tuples, must be end of data. */
  21.         if (fsstate->next_tuple >= fsstate->num_tuples)
  22.             return ExecClearTuple(slot);
  23.     }

  24.     /*
  25.      * Return the next tuple.
  26.      */
  27.     ExecStoreTuple(fsstate->tuples[fsstate->next_tuple++],
  28.                  slot,
  29.                  InvalidBuffer,
  30.                  false);

  31.     return slot;
  32. }

增删改则是通过 prepare 一个查询,然后通过传递参数的方式一条条执行
在原有的增删改接口中判断,如果是 foreign table, 则进入增删改远程表流程
以delete 为例:
如:delete from t_foreign
1. 先通过 ForeignScan 接口,获取远程数据库的一条元组 的 ctid
2. 将该ctid 传递到 ExecDelete 接口中,该函数调用 postgresExecForeignDelete 进入删除外部表操作
3.  为 delete 语句  DELETE FROM public.t2 WHERE ctid = $1 生成执行计划
4. 在远程数据库执行 3 生成的计划,删除一条元组
5. 重复 1。由于计划只需生成1次,所以后面的删除不需要重新生成计划。

Insert 和 Update 同理。



阅读(3654) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~