创建分布式表,需要先定义一个表。用常规的uxdb的create table语句定义表即可。
CREATE TABLE github_events( event_id bigint, event_type text, event_public boolean, repo_id bigint, payload jsonb, repo jsonb, actor jsonb, org jsonb, created_at timestamp);
接下来,可以使用create_distributed_table()函数指定表分发列并创建分片。
SELECT create_distributed_table ('github_events','repo_id');
此函数通知uxmpp通过repo_id列对表github_events进行分发。根据uxmpp.shard_count和uxmpp.shard_replication_factor的值在worker上创建分片。总共创建uxmpp.shard_count个分片数,并根据uxmpp.shard_replication_factor的值进行复制,复制的副本具有和原表相同的表结构,包括模式、索引和约束。
每个分片都有一个唯一的分片ID,但是副本和原表具有相同的分片ID。每个分片在worker节点上是以名为”tablename_shardid”的常规表显示的,其中tablename是分布式表的名称,shardid是该分片的唯一ID。
前面使用的 create_distributed_table创建分布式表适用于空表和非空表。在非空表中使用会自动对数据进行分布,并会有相应的提示。如:
CREATE TABLE series AS SELECT i FROM generate_series(1,1000000) i; SELECT create_distributed_table('series','i');
非空表的分布式会有数据迁移的操作,因此分发过程中禁止对该表写入数据。如果是挂起的写入,则在数据分发完成之后,按分布式处理。同时,读取也是按分布式处理。
分布式表协同定位
协同定位是在相同的机器上保留相关信息,用以实现高效的关系操作,同时,可有效的利用整个数据集的水平可伸缩性。
表是分组的,如果需要手动控制表的分组,那么在创建分布式表create_distributed_table的时候使用可选参数colocate_with。如果不选该参数,则使用缺省值,默认是default,该值将具有相同分发列类型、相同分片数和相同复制因子的表放在一个组。如下,对t1表和t2表分片表是分发列类型相同,都用的默认分片数和复制因子,故表t1和t2会有相同的分组,例如a=1行和m=1的行放在同一个节点上。
CREATE TABLE t1(a int,b char(10)); CREATE TABLE t2(m int,n char(10)); SELECT create_distributed_table('t1','a'); SELECT create_distributed_table('t2','m');
如果澳门游戏平台注册网站希望每个表有自己单独的分组,则可以指定colocate_with参数值为none。
SELECT create_distributed_table ('t1','a',colocate_with => 'none');
如果共同定位多个表,可以先分配一个表,然后再将其他表放入该表的组中。例如:
CREATE TABLE test(id int, id2 int, t text); CREATE TABLE test1(id int, id2 int, t text); CREATE TABLE test2(id int, id2 int, t text); SELECT create_distributed_table('test', 'id'); SELECT create_distributed_table('test1', 'id2', colocate_with=>'test'); SELECT create_distributed_table('test2', 'id2', colocate_with=>'test');
表ux_dist_partition中可以看到哪些表分配给哪些组(colocationid字段),有关组的信息可以通过表ux_dist_colocation查看。
上述方法是将表分配到多个水平分片中,澳门游戏平台注册网站这还有另一种方法是将表分配到单个分片中并将分片复制到每个worker节点上。以这种方式分发的表称为参考表。主要是为了存储多个节点频繁访问的数据。常见的参考表有:
需要与较大的分布式表连接的小表。
多租户应用中的缺少租户ID列或者与租户无关的表。
跨多列的唯一约束的小表。
创建参考表可用
SELECT create_reference_table('tablename');
uxmpp会自动传播多种DDL语句。那么澳门游戏平台注册网站在协调节点(master)上修改表,同时也会更新到对应的worker节点上的对应的分片表。当然,不是所有的DDL语句都可以传播,有一部分需要手动在各个节点上进行修改,还有一部分目前是不支持的,例如修改分发列。
自动传播DDL可以通过设置参数uxmpp.enable_ddl_propagation来启用或禁止,默认是启用。
uxmpp自动传播大多数的ALTER TABLE命令。如修改表名,列名,添加列,删除列,修改列的类型,这些操作和在单机版的uxdb数据库中是一样的。但是,不建议直接对分布列进行相关的修改操作,且分布列不支持列的删除和类型修改。
使用uxmpp不影响数据库约束的使用。例如在分布式表上创建主键和外键:
--创建一个货物、订单、库存的关系表 CREATE TABLE goods(gid varchar(20),gname varchar(20),gprice int); CREATE TABLE orders(oid varchar(20),gid varchar(20),onumber int); CREATE TABLE stock(sid varchar(20),gid varchar(20),snumber int); --添加主键(唯一约束必须在分发列之前创建) ALTER TABLE goods ADD PRIMARY KEY (gid); ALTER TABLE orders ADD PRIMARY KEY (oid,gid); ALTER TABLE stock ADD PRIMARY KEY (sid,gid); --分发表 SELECT create_distributed_table ('goods','gid'); SELECT create_distributed_table ('orders','oid'); SELECT create_distributed_table ('stock','sid'); --添加外键 ALTER TABLE orders ADD CONSTRAINT goods_orders_fk FOREIGN KEY(oid) REFERENCES goods(gid); ALTER TABLE stock ADD CONSTRAINT goods_stock_fk FOREIGN KEY(sid) REFERENCES goods(gid); --非空约束 ALTER TABLE orders ALTER COLUMN onumber SET NOT NULL;
uxmpp支持添加和删除索引。
CREATE INDEX date_idx ON orders USING BRIN(odate); DROP INDEX date_idx ;
由于添加索引的时候会锁定表,在uxmpp适用的多租户模型中是不可取的。为了避免这种问题,澳门游戏平台注册网站用到下述方法创建索引,虽然可能会花费更多的时间。但是它不会锁定表,因此对于多租户模型来说是非常有用的。
CREATE INDEX CONCURRENTLY date_idx ON orders USING BRIN(odate);
要将数据插入分布式表,可以使用标准的INSERT命令:
INSERT INTO test VALUES (0,0,'uxsino'); INSERT INTO test VALUES (1,1,'agent'),(2,2,'mpp');
给分布式表插入行的时候,必须要指定分发列,即分发列不能为空。数据会根据分发列将数据路由到对应的分片上。
当然,澳门游戏平台注册网站还支持批量加载,那么澳门游戏平台注册网站可以直接使用uxdb的copy命令:
COPYtable_name
[ (column_name
[, ...] ) ] FROM { 'filename
' | PROGRAM 'command
' | STDIN } [ [ WITH ] (option
[, ...] ) ]
分片没有快照隔离的概念,那么当澳门游戏平台注册网站在copy的同时进行select的时候,可能会在某些分片上看到澳门游戏平台注册网站copy的数据,但在其他分片上可能没有。如果copy无法连接到其他分片,那么它的行为相当于insert,如果连接到分片发生故障,则回滚事物,不会对元数据进行更改。
在很多uxmpp的数据模型下,澳门游戏平台注册网站对大量数据进行快速查询,需要亚秒级的反应。那么澳门游戏平台注册网站快速查询的一种方法就是可以提前计算和保存聚合。例如重复执行一个聚合查询的时,它必须遍历每个相关的行并进行重新计算整个数据集的结果,那么将数据分别汇总到每小时或者每天进行保存,这样就避免了再运行的时候处理原始数据的成本。当聚合的汇总足够多的时候,且不在需要完整的详细信息时候,旧数据则可以被删除,这样也会节省存储空间。
综上所述,需要注意:
查询和插入表由类似的列分发
选择查询的时候,条件应该带分布列
插入必须包括分布列
对于uxmpp的更新和删除可以使用标准的uxdb的UPDATE和DELETE命令:
DELETE FROM [ ONLY ]table_name
[ * ] [ [ AS ]alias
] [ USINGusing_list
] [ WHEREcondition
| WHERE CURRENT OFcursor_name
] [ RETURNING * |output_expression
[ [ AS ]output_name
] [, ...] ]
UPDATE [ ONLY ]table_name
[ * ] [ [ AS ]alias
] SET {column_name
= {expression
| DEFAULT } | (column_name
[, ...] ) = [ ROW ] ( {expression
| DEFAULT } [, ...] ) | (column_name
[, ...] ) = (sub-SELECT
) } [, ...] [ FROMfrom_list
] [ WHEREcondition
| WHERE CURRENT OFcursor_name
] [ RETURNING * |output_expression
[ [ AS ]output_name
] [, ...] ]
分布式表更新的时候,不能修改分布式列。
uxmpp是一个扩展,扩展了UXDB以实现分布式。那么澳门游戏平台注册网站可以在master上使用标准的UXDB的SELECT查询。uxmpp可以并行化复杂的选择、分组、排序以及JOIN的SELECT查询,以加快查询性能。uxmpp将SELECT查询分成小的查询片段分配给下面的worker,并将其结果合并返回给用户。
uxmpp支持并行化uxdb的大多数聚合函数。
uxmpp以多种方式支持count(distinct)聚合。如果count(distinct)聚合在分发列上,则可以直接下发到worker。如果没有在分发列上,那么将会在每个worker上运行select distinct语句,然后将结果返回给master,在master上进行最终的count。
对于包含多个count(distinct)聚合查询的时候,出具传输会变得很慢。如:
SELECT count(distinct a), count(distinct b), count(distinct c)FROM table_abc;
uxmpp支持劝拿庞蜗菲教ㄗ⒉嵬锯数量的表之间的equi-join,并且可以不考虑表的大小和分布方式。查询规划器会根据表的分布方式选择最优的连接方法和连接顺序。并创建一个连接计划,用以使用最小的网络资源传输数据。
当两个表是协同表的时候,它们可以在公共分布列上实现最高效的join连接。这也是分布式表中join连接的最优方法。
join连接要确保表分布到相同数量的分片中,且分发列类型有相应的类型。如果连接不同类型的列(如int和bigint)可能会出现问题。
参考表可用作“维度”表,以便与大表连接。由于参考表是在所有worker节点上完全复制,因此可以将与参考表的连接分解为每个worker上的本地连接,并且可以并行执行。这类似于协同表连接的升级版,因为参考表不用在任何特定的列上分发,并且可以用任何列进行join连接。