Citus 分布式 PostgreSQL 集群 - SQL Reference(SQL支持和变通方案

2022-05-09 00:00:00 查询 支持 分布式 节点 适用于


由于 Citus 通过扩展 PostgreSQL 提供分布式功能,因此它与 PostgreSQL 结构兼容。这意味着用户可以使用丰富且可扩展的 PostgreSQL 生态系统附带的工具和功能来处理使用 Citus 创建的分布式表。

Citus 对它能够在单个工作节点上执行的任何查询具有 的 SQL 覆盖率。 在访问有关单个租户的信息时,此类查询在多租户应用程序中很常见。

甚至跨节点查询(用于并行计算)也支持大多数 SQL 功能。 但是,组合来自多个节点的信息的查询不支持某些 SQL 功能。

跨节点 SQL 查询的限制:

SELECT … FOR UPDATE 仅适用于单分片查询
TABLESAMPLE 仅适用于单分片查询
关联子查询仅当关联在分布列上时才受支持。
分布式表之间的外连接仅在分布列上受支持。
仅当分布式表在外侧时,才支持分布式表和引用表或本地表之间的外连接
递归 CTE 仅适用于单分片查询
分组集仅适用于单分片查询
要了解有关 PostgreSQL 及其功能的更多信息,您可以访问 PostgreSQL 文档。有关 PostgreSQL SQL 命令方言(可供 Citus 用户按原样使用)的详细参考,您可以查看 SQL 命令参考。

变通方案
在尝试变通方案之前,请考虑 Citus 是否适合您的情况。Citus 当前版本适用于实时分析和多租户用例。

Citus 支持多租户用例中的所有 SQL 语句。即使在跨节点查询的实时分析用例中,Citus 也支持大多数语句。 Citus 不支持的 PostgreSQL 特性中列出了几种不受支持的查询类型? 许多不受支持的功能都有变通方案;以下是一些有用的。

使用 CTE 解决限制
当 SQL 查询不受支持时,解决它的一种方法是使用 CTE,它使用我们所谓的 pull-push 执行。

SELECT * FROM ref LEFT JOIN dist USING (id) WHERE dist.value > 10;
/*
ERROR: cannot pushdown the subquery
DETAIL: There exist a reference table in the outer part of the outer join
*/
要解决此限制,您可以通过将分布式部分包装在 CTE 中来将查询转换为路由器查询

WITH x AS (SELECT * FROM dist WHERE dist.value > 10)
SELECT * FROM ref LEFT JOIN x USING (id);
请记住,coordinator 会将 CTE 的结果发送给所有需要它进行处理的 worker。 因此,好将具体的过滤器和限制添加到内部查询中,或者聚合表。 这减少了此类查询可能导致的网络开销。在子查询/CTE 网络开销中了解更多信息。

临时表:不得已的解决方法
即使通过子查询使用推拉执行,仍有一些查询不受支持。其中之一是在分布式表上使用分组集。

在我们的实时分析教程中,我们创建了一个名为 github_events 的表,由 user_id 列分布。让我们查询它并找到一组预选的 repos 的早事件,按事件类型和事件公开的组合分组。一种方便的方法是使用分组集。 但是,如前所述,分布式查询尚不支持此功能:

-- this won't work
SELECT repo_id, event_type, event_public,
grouping(event_type, event_public),
min(created_at)
FROM github_events
WHERE repo_id IN (8514, 15435, 19438, 21692)
GROUP BY repo_id, ROLLUP(event_type, event_public);
ERROR: could not run distributed query with GROUPING
HINT: Consider using an equality filter on the distributed table's partition column.
不过,有一个窍门。我们可以将相关信息作为临时表拉取到 coordinator:

-- grab the data, minus the aggregate, into a local table

CREATE TEMP TABLE results AS (
SELECT repo_id, event_type, event_public, created_at
FROM github_events
WHERE repo_id IN (8514, 15435, 19438, 21692)
);

-- now run the aggregate locally

SELECT repo_id, event_type, event_public,
grouping(event_type, event_public),
min(created_at)
FROM results
GROUP BY repo_id, ROLLUP(event_type, event_public);
repo_id | event_type | event_public | grouping | min
---------+-------------------+--------------+----------+---------------------
8514 | PullRequestEvent | t | 0 | 2016-12-01 05:32:54
8514 | IssueCommentEvent | t | 0 | 2016-12-01 05:32:57
19438 | IssueCommentEvent | t | 0 | 2016-12-01 05:48:56
21692 | WatchEvent | t | 0 | 2016-12-01 06:01:23
15435 | WatchEvent | t | 0 | 2016-12-01 05:40:24
21692 | WatchEvent | | 1 | 2016-12-01 06:01:23
15435 | WatchEvent | | 1 | 2016-12-01 05:40:24
8514 | PullRequestEvent | | 1 | 2016-12-01 05:32:54
8514 | IssueCommentEvent | | 1 | 2016-12-01 05:32:57
19438 | IssueCommentEvent | | 1 | 2016-12-01 05:48:56
15435 | | | 3 | 2016-12-01 05:40:24
21692 | | | 3 | 2016-12-01 06:01:23
19438 | | | 3 | 2016-12-01 05:48:56
8514 | | | 3 | 2016-12-01 05:32:54
在 coordinator 上创建临时表是后的手段。它受节点的磁盘大小和 CPU 的限制。
————————————————
版权声明:本文为CSDN博主「为为少」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/o__cc/article/details/124030939

相关文章