Citus 分散式 PostgreSQL 叢集 - SQL Reference(SQL支援和變通方案)

為少發表於2022-04-02

image

由於 Citus 通過擴充套件 PostgreSQL 提供分散式功能,因此它與 PostgreSQL 結構相容。這意味著使用者可以使用豐富且可擴充套件的 PostgreSQL 生態系統附帶的工具和功能來處理使用 Citus 建立的分散式表。

Citus 對它能夠在單個工作節點上執行的任何查詢具有 100%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 的限制。

更多

  1. Citus 分散式 PostgreSQL 叢集 - SQL Reference(建立和修改分散式表 DDL)
  2. Citus 分散式 PostgreSQL 叢集 - SQL Reference(攝取、修改資料 DML)
  3. Citus 分散式 PostgreSQL 叢集 - SQL Reference(查詢分散式表 SQL)
  4. Citus 分散式 PostgreSQL 叢集 - SQL Reference(查詢處理)

相關文章