当前位置: 首页 > 科技观察

CitusDistributedPostgreSQLCluster-SQLReference(Ingest,ModifyDataDML)

时间:2023-03-12 03:02:38 科技观察

InsertData要将数据插入分布式表,可以使用标准的PostgreSQLINSERT命令。例如,我们从Github存档数据集中随机选择两行。插入http://www.postgresql.org/docs/current/static/sql-insert.html/*CREATETABLEgithub_events(event_idbigint,event_typetext,event_publicboolean,repo_idbigint,payloadjsonb,repojsonb,actorjsonb,orgjsonb,created_attimestamp);*/INSERTINTOgithub_eventsVALUES(2489373118,'PublicEvent','t',24509048,'{}','{"id":24509048,"url":"https://api.github.com/repos/SabinaS/csee6868","name":"SabinaS/csee6868"}','{"id":2955009,"url":"https://api.github.com/users/SabinaS","login":"SabinaS","avatar_url":"https://img.ydisp.cn/news/20220630/h2ktxjpvw2g.jpg"gravatar_id":""}',NULL,'2015-01-0100:09:13');INSERTINTOgithub_eventsVALUES(2489368389,'WatchEvent','t',28229924,'{"action":"started"}','{"id":28229924,"url":"https://api.github.com/repos/inf0rmer/blanket","name":"inf0rmer/blanket"}','{"id":1405427,"url":"https://api.github.com/users/tategakibunko","login":"tategakibunko","avatar_url":"https://img.ydisp.cn/news/20220630/eayna4n2qt0.png"gravatar_id":""}',NULL,'2015-01-0100:00:24');向分布式表中插入行时,必须根据分布列指定插入行的分布列,Citus确定插入应路由到的正确分片。然后将查询转发到正确的分片,并在该分片的所有副本上执行远程插入命令。有时将多个插入语句放在包含多行的单个插入中会很方便。它也比重复数据库查询更有效。例如,上一节中的示例可以像这样一次性加载:INSERTINTOgithub_eventsVALUES(2489373118,'PublicEvent','t',24509048,'{}','{"id":24509048,"url":"https://api.github.com/repos/SabinaS/csee6868","name":"SabinaS/csee6868"}','{"id":2955009,"url":"https://api.github.com/users/SabinaS","login":"SabinaS","avatar_url":"https://img.ydisp.cn/news/20220630/h2ktxjpvw2g.jpg"gravatar_id":""}',NULL,'2015-01-0100:09:13'),(2489368389,'WatchEvent','t',28229924,'{"action":"started"}','{"id":28229924,"url":"https://api.github.com/repos/inf0rmer/blanket","name":"inf0rmer/blanket"}','{"id":1405427,"url":"https://api.github.com/users/tategakibunko","login":"tategakibunko","avatar_url":"https://img.ydisp.cn/news/20220630/eayna4n2qt0.png"gravatar_id":""}',NULL,'2015-01-0100:00:24');“FromSelect”子句(分布式聚合)Citus还支持INSERT...SELECT语句——根据选择查询的结果插入行。这是一种填充表的便捷方法,还允许使用ONCONFLICT子句“更新插入”,这是进行分布式聚合的最简单方法。分布式汇总https://docs.citusdata.com/en/v11.0-beta/develop/reference_dml.html#rollups在Citus中,可以通过三种方式从select语句插入。第一个是如果源表和目标表位于同一位置并且选择/插入语句都包含分布列。在这种情况下,Citus可以下推INSERT...SELECT语句在所有节点上并行执行。当SELECT查询不需要协调器上的合并步骤时,可能会发生重新分区优化。它不适用于以下需要合并步骤的SQL函数:ORDERBYLIMITOFFSETGROUPBYWindowfunctionswhenpartitioningbyanon-distributioncolumninthesourcetablewhenthedistributioncolumnisnotpartofthegroupkey即重新分区连接)当源表和目标表未位于同一位置并且无法应用重新分区优化时,Citus使用第三种方式执行INSERT...SELECT。它从工作节点中选择结果并将数据拉到协调器节点。协调器将行重定向回适当的分片。这种方法效率低下,因为所有数据都必须通过单个节点。如果不确定Citus使用哪种方法,请使用EXPLAIN命令,如PostgreSQL调优中所述。当目标表有大量分片时,禁用重新分区可能是明智的,请参阅citus.enable_repartitioned_insert_select(布尔值)。PostgreSQL调整https://docs.citusdata.com/en/v11.0-beta/performance/performance_tuning.html#postgresql-tuningcitus.enable_repartitioned_insert_select(布尔值)https://docs.citusdata.com/en/v11.0-beta/develop/api_guc.html#enable-repartitioned-insert-selectCOPY命令(批量加载)要从文件中批量加载数据,您可以直接使用PostgreSQL的\COPY命令。首先通过运行下载我们的示例github_events数据集:wgethttp://examples.citusdata.com/github_archive/github_events-2015-01-01-{0..5}.csv.gzgzip-dgithub_events-2015-01-01-*.gz然后,你可以使用psql复制数据(注意这个数据需要数据库有UTF8编码):\COPYgithub_eventsFROM'github_events-2015-01-01-0.csv'WITH(formatCSV)注意:no跨分片的快照隔离概念,这意味着与COPY同时运行的多分片SELECT可能会看到它在某些分片上提交,但在其他分片上看不到。如果用户正在存储事件数据,他可能偶尔会观察到最近数据中的小间隙。如果这是一个问题,则由应用程序来处理它(例如,从查询中排除最新数据,或使用一些锁)。如果COPY无法为分片put打开连接,那么它的行为与INSERT相同,将put标记为不活动,除非没有更多活动put。如果连接后发生任何其他故障,事务将回滚,因此元数据不会更改。聚合事件数据管道和使用汇总缓存的实时仪表板等应用程序需要对大量数据进行亚秒级查询。加快这些查询的一种方法是提前计算和保存聚合。这称为“汇总”数据,它避免了在运行时处理原始数据的成本。作为一个额外的好处,将时间序列数据聚合到每小时或每天的统计数据中也可以节省空间。当不再需要所有详细信息并且聚合足够时,可以删除旧数据。例如,这是一个通过url跟踪页面浏览量的分布式表:选择create_distributed_table('page_views','site_id');一旦表中填充了数据,我们就可以运行聚合查询来计算每天每个URL的页面浏览量,仅限于给定的站点和年份。--网站5上每个网址每天有多少浏览量?选择view_time::dateASday,site_id,url,count(*)ASview_countFROMpage_viewsWHEREsite_id=5ANDview_time>=date'2016-01-01'ANDview_time=date'2017-01-01'ANDview_time=日期'2016-01-01'ANDday--从给定日期开始滚动,--必要时更新每日页面浏览量INSERTINTOdaily_page_views(day,site_id,url,view_count)SELECTview_time::dateASday,site_id,url,count(*)ASview_countFROMpage_viewsWHEREview_time>=date'2017-01-01'组按view_time::date,site_id,urlONCONFLICT(day,url,site_id)DOUPDATESETview_count=daily_page_views.view_count+EXCLUDED.view_count;更新和删除您可以使用标准的PostgreSQL更新和删除命令更新或删除分布式表中的行。从github_eventsWHERErepo_idIN(24509048,24509049)中删除;更新github_eventsSETevent_public=TRUEWHERE(org->>'id')::int=5430905;更新http://www.postgresql.org/docs/current/static/sql-update.htmlDELETEhttp://www.postgresql.org/docs/current/static/sql-delete.html当更新/删除影响多个分片时,如上例所示,Citus默认使用单阶段提交协议。为了增加安全性,您可以通过设置启用两阶段提交。SETcitus.multi_shard_commit_protocol='2pc';如果更新或删除仅影响单个分片,则它会在单个工作节点内运行。在这种情况下,不需要启用2PC。这通常发生在过滤器被表的分布列更新或删除时:--因为github_events是由repo_id分布的,--这将在单个工作节点中执行DELETEFROMgithub_eventsWHERErepo_id=206084;另外,当处理单个分片时,Citus支持SELECT...FORUPDATE。这是对象关系映射器(ORM)有时为了安全起见使用的一种技术:加载行是在应用程序代码中计算的,更新行基于计算选择要更新的行在它们上设置写锁,以防止其他进程导致“丢失更新”异常。开始;--为repo选择事件,但是--锁定它们以写入SELECT*FROMgithub_eventsWHERErepo_id=206084FORUPDATE;--计算期望值event_public使用--使用这些行的应用程序逻辑...--现在更新更新github_eventsSETevent_public=:our_new_valueWHERErepo_id=206084;COMMIT;此功能仅支持散列分布表和引用表,并且仅支持replication_factor为1的表。replication_factorhttps://docs.citusdata.com/en/v11.0-beta/develop/api_guc.html#replication-factor最大化写入性能在大型机器上,INSERT和UPDATE/DELETE语句都可以扩展到大约50,000个查询。然而,要达到这个速度,您将需要使用许多并行的、长期存在的连接,并考虑如何处理锁定。有关详细信息,您可以查阅我们文档的横向扩展数据摄取部分。横向扩展数据摄取https://docs.citusdata.com/en/v11.0-beta/performance/performance_tuning.html#scaling-data-ingestion