全部產品
Search
文件中心

PolarDB:使用說明

更新時間:May 08, 2025

列存索引的目標是提供一個最簡便的方案,以加速業務中複雜耗時的SQL語句。您可以參考快速入門中的內容,以配置叢集的HTAP負載處理能力。此外,您可以參考進階使用中的內容對列存索引進行定製以滿足特定的業務需求。

快速入門

1. 添加列存索引唯讀節點

登入PolarDB控制台,在左側導覽列單擊叢集列表,選擇叢集所在地區,找到目的地組群。單擊操作欄中的增刪節點,添加列存索引唯讀節點。image

說明
  • 若您在購買叢集時已添加列存索引唯讀節點,請忽略當前步驟。

  • 您的叢集需滿足列存索引的版本要求。更多資訊,請參見列存索引唯讀節點

2. 配置行列分流方案

您可以根據業務需求選擇行列自動分流或手動分流兩種方式,來使用列存索引。

  • 行列自動分流:如果您的業務中,OLTP類型業務與OLAP類型業務是基於同一個應用程式訪問資料庫,則可以通過將兩類業務的讀請求根據預估執行代價(掃描行數)進行自動分流,從而分別路由至列存索引唯讀節點或唯讀行存節點。

  • 行列手動分流:如果您的業務中,OLTP類型業務與OLAP類型業務是基於不同應用程式訪問資料庫,則可以為這些應用程式分別配置不同的叢集地址。隨後,將列存索引唯讀節點和唯讀行存節點分別配置到不同叢集地址(Endpoint)的服務節點中,從而實現行存和列存的分流。

行列自動分流

前往叢集詳情頁面,在資料庫連接地區,修改叢集地址行存/列存自動引流選項為開啟image

說明

行列手動分流

前往叢集詳情頁面,在資料庫連接地區,建立一個自訂地址,服務節點應僅包含列存索引唯讀節點image

3. 添加列存索引

您可以根據業務需求選擇手動添加或自動添加兩種方式,來為您的業務表添加列存索引。

重要

查詢SQL語句中所涉及的所有列均需被列存索引完全覆蓋,才能使用列存索引實現查詢加速。

手動添加

列存索引為您提供全面的DDL語句,以支援您為業務表添加或刪除列存索引。您可以根據實際需求進行選擇:

DDL文法

樣本

建表時建立列存索引

-- 為某一列添加列存索引
CREATE TABLE <table_name>(
  <column_name_1> INT COMMENT 'COLUMNAR=1',
  <column_name_2> VARCHAR(100)
) ENGINE InnoDB;

-- 為全表添加列存索引
CREATE TABLE <table_name>(
  <column_name_1> INT,
  <column_name_2> VARCHAR(100)
) ENGINE InnoDB COMMENT 'COLUMNAR=1';

動態增加或刪除列存索引

-- 為指定列添加列存索引
ALTER TABLE <table_name> MODIFY COLUMN <column_name_1> INT COMMENT 'COLUMNAR=1';
               
-- 為整個表添加列存索引
ALTER TABLE <table_name> COMMENT 'COLUMNAR=1';

庫表級(批量)增加或刪除列存索引

-- 為整個表添加列存索引
CREATE COLUMNAR INDEX ON <db_name>.<table_name>;

-- 為整個庫添加列存索引
CREATE COLUMNAR INDEX FOR TABLES IN <db_name>;
說明
  • 添加列存索引時,您可以保留原有注釋。例如:ALTER TABLE <table_name> COMMENT 'COLUMNAR=1 <原有注釋>';

  • 預設情況下,庫表級(批量)增加列存索引時,表注釋會修改為'COLUMNAR=1 <原有注釋>'

自動添加

列存索引提供的自動無感提速(AutoIndex)功能,能夠根據您的慢SQL自動建立列存索引,從而顯著提升慢SQL的執行速度,無需您深入理解每一條慢SQL進行調優。隨著應用負載的變化,自動列存索引提速功能會持續監控並調整列存索引策略,以確保PolarDB叢集維持在最佳效能狀態。

您只需在PolarDB叢集詳情頁面,開啟自動列存索引提速功能即可體驗該功能帶來的效果:

image

(可選)4. 查詢列存索引構建進度

手動添加列存索引後,需要查看列存索引構建的執行進度,等待列存索引構建完成,即可體驗列存索引的查詢加速效果。

SELECT * FROM INFORMATION_SCHEMA.IMCI_ASYNC_DDL_STATS;

樣本如下:通過查看STATUS狀態是否為Safe to read,可以確認列存索引是否已構建完成。

+-------------+------------+---------------------+---------------------+---------------------+--------------+------------------+-----------------+-------------+-------------+-------------+------------+--------------+-----------+-------------------+-----------------+
| SCHEMA_NAME | TABLE_NAME | CREATED_AT          | STARTED_AT          | FINISHED_AT         | STATUS       | APPROXIMATE_ROWS | SCANNED_ROWS    | SCAN_SECOND | SORT_ROUNDS | SORT_SECOND | BUILD_ROWS | BUILD_SECOND | AVG_SPEED | SPEED_LAST_SECOND | ESTIMATE_SECOND |
+-------------+------------+---------------------+---------------------+---------------------+--------------+------------------+-----------------+-------------+-------------+-------------+------------+--------------+-----------+-------------------+-----------------+
| tpch        | lineitem   | 2024-10-21 13:44:02 | 2024-10-21 13:44:02 | 2024-10-21 13:50:11 | Safe to read | 590446240        | 600037902(100%) | 369         | 0           | 0           | 0(0%)      | 0            | 1625058   | 0                 | 0               |
+-------------+------------+---------------------+---------------------+---------------------+--------------+------------------+-----------------+-------------+-------------+-------------+------------+--------------+-----------+-------------------+-----------------+
1 row in set, 1 warning (0.00 sec)

(可選)5. 檢查SQL語句是否使用列存索引

列存執行計畫以橫向樹的形式輸出,該格式與行存執行計畫的輸出格式存在明顯區別。您可以通過使用Explain查看SQL的執行計畫,來判斷某條SQL語句是否可以使用列存索引加速功能。樣本如下:

列存執行計畫(橫向樹形式)

+----+----------------------------+----------+--------+--------+-----------------------------------------------------------------------------+
| ID | Operator                   | Name     | E-Rows | E-Cost | Extra Info                                                                  |
+----+----------------------------+----------+--------+--------+-----------------------------------------------------------------------------+
|  1 | Select Statement           |          |        |        | IMCI Execution Plan (max_dop = 4, max_query_mem = 858993459)                |
|  2 | └─Sort                     |          |        |        | Sort Key: revenue DESC,o_orderdate ASC                                      |
|  3 |   └─Hash Groupby           |          |        |        | Group Key: (lineitem.L_ORDERKEY, orders.O_ORDERDATE, orders.O_SHIPPRIORITY) |
|  4 |     └─Hash Join            |          |        |        | Join Cond: orders.O_ORDERKEY = lineitem.L_ORDERKEY                          |
|  5 |       ├─Hash Join          |          |        |        | Join Cond: customer.C_CUSTKEY = orders.O_CUSTKEY                            |
|  6 |       │ ├─Table Scan       | customer |        |        | Cond: (C_MKTSEGMENT = "BUILDING")                                           |
|  7 |       │ └─Table Scan       | orders   |        |        | Cond: (O_ORDERDATE < 03/24/1995)                                            |
|  8 |       └─Table Scan         | lineitem |        |        | Cond: (L_SHIPDATE > 03/24/1995)                                             |
+----+----------------------------+----------+--------+--------+-----------------------------------------------------------------------------+
8 rows in set (0.01 sec)

行存執行計畫

+----+-------------+----------+------------+------+--------------------+------------+---------+-----------------------------+--------+----------+----------------------------------------------+
| id | select_type | table    | partitions | type | possible_keys      | key        | key_len | ref                         | rows   | filtered | Extra                                        |
+----+-------------+----------+------------+------+--------------------+------------+---------+-----------------------------+--------+----------+----------------------------------------------+
|  1 | SIMPLE      | customer | NULL       | ALL  | PRIMARY            | NULL       | NULL    | NULL                        | 147630 |    10.00 | Using where; Using temporary; Using filesort |
|  1 | SIMPLE      | orders   | NULL       | ref  | PRIMARY,ORDERS_FK1 | ORDERS_FK1 | 4       | tpch100g.customer.C_CUSTKEY |     14 |    33.33 | Using where                                  |
|  1 | SIMPLE      | lineitem | NULL       | ref  | PRIMARY            | PRIMARY    | 4       | tpch100g.orders.O_ORDERKEY  |      4 |    33.33 | Using where                                  |
+----+-------------+----------+------------+------+--------------------+------------+---------+-----------------------------+--------+----------+----------------------------------------------+
3 rows in set, 1 warning (0.00 sec)

協助工具輔助

在使用列存索引查詢複雜SQL語句時,您需要檢查SQL語句中是否存在未被索引覆蓋的列。如果發現有未被列存索引覆蓋的列,您可以針對該SQL語句擷取建立列存索引的DDL語句,或者針對某個業務批量擷取建立列存索引的DDL語句。執行擷取的DDL語句後,確保SQL語句中的所有列均被列存索引覆蓋,才可使用列存索引進行查詢加速。

PolarDB叢集內建的預存程序如下:

常見問題

為什麼SQL語句並沒有走列存索引?

新增列存索引唯讀節點後,需要為SQL語句中所查詢的表都增加列存索引,且SQL語句的預估執行代價超過一定閾值,該SQL語句才會使用列索引進行查詢。另外,SQL語句需要被轉寄到列存索引唯讀節點,才可以使用列存索引進行查詢加速。一般來說,如果一條SQL語句無法使用列存索引進行查詢,可以按照以下步驟進行問題排查:

  1. 確認SQL是否被轉寄至列存索引唯讀節點。

    • 使用的資料庫連接地址中的服務節點是否包含列存索引唯讀節點。

    • 通過SQL洞察功能,可以確認SQL是否被轉寄到了列存索引唯讀節點。具體資訊,請參見SQL洞察

    如果使用叢集地址並開啟行存/列存自動引流,同時SQL的預估執行代價高於設定的閾值loose_imci_ap_thresholdloose_cost_threshold_for_imci,則資料庫代理將會將SQL轉寄至列存索引唯讀節點。此外,您可以在SQL語句的SELECT關鍵字前添加HINT文法/*FORCE_IMCI_NODES*/以強制指定將SQL轉寄到列存索引唯讀節點。具體資訊,請參見配置自動引流閾值。樣本如下:

    核心版本8.0.1.1.39與8.0.2.2.23及之後的版本,參數loose_imci_ap_threshold被棄用,統一使用參數loose_cost_threshold_for_imci
    /*FORCE_IMCI_NODES*/EXPLAIN SELECT COUNT(*) FROM t1 WHERE t1.a > 1;
    建立一個新的資料庫連接地址,可以保證SQL語句一定會被轉寄到列存索引唯讀節點上執行。具體資訊,請參見建立一個新的資料庫連接地址
  2. SQL的預估執行代價是否高於設定的閾值。

    在列存索引唯讀節點上,最佳化器會對SQL進行執行代價預估,如果預估執行代價高於設定的閾值loose_imci_ap_thresholdloose_cost_threshold_for_imci,則使用列存索引進行查詢,否則將使用原有的行索引進行查詢。

    在確認SQL被轉寄到列存索引唯讀節點後,如果通過EXPLAIN查看執行計畫依然沒有使用列存索引,可以通過比較預估執行代價與預設的閾值,判斷是否是預估執行代價過小而沒有使用列存索引。您可以通過查詢Last_query_cost變數擷取“上一條SQL的預估執行代價”:

    -- 使用EXPLAIN查看SQL的執行計畫
    EXPLAIN SELECT * FROM t1;
    -- 擷取上一條SQL的預估執行代價
    SHOW STATUS LIKE 'Last_query_cost';
    如果使用叢集地址串連資料庫,建議您在SHOW STATUS LIKE 'Last_query_cost'前添加HINT文法/*ROUTE_TO_LAST_USED*/,以確保能夠在正確的節點上查詢到上一條語句的預估執行代價。例如,/*ROUTE_TO_LAST_USED*/SHOW STATUS LIKE 'Last_query_cost';

    若SQL的預估執行代價小於預設的閾值,可以考慮調整loose_imci_ap_thresholdloose_cost_threshold_for_imci的值。例如,使用HINT文法調整單條SQL的預設閾值:

    /*FORCE_IMCI_NODES*/EXPLAIN SELECT /*+ SET_VAR(cost_threshold_for_imci=0) */ COUNT(*) FROM t1 WHERE t1.a > 1;
  3. SQL中所涉及的表或列是否被列存索引完全覆蓋。

    可以通過內建的預存程序dbms_imci.check_columnar_index('<query_string>'),檢查SQL語句中的表或列是否已建立列存索引。具體資訊,請參見檢查SQL語句中的表或列是否已建立列存索引。樣本如下:

    CALL dbms_imci.check_columnar_index('SELECT COUNT(*) FROM t1 WHERE t1.a > 1');

    如果SQL未被列存索引完全覆蓋,調用該預存程序將返回未被覆蓋的表和列,您需對返回的表和列逐一建立列存索引。如果已經完全被列存索引覆蓋,則調用該預存程序將返回空結果集。

  4. 是否有不支援的SQL特性。

    通過查看列存索引文法使用限制,確認某個SQL特性是否支援列存索引。具體資訊,請參見列存索引文法使用限制

如按上述步驟排查後,SQL語句仍然沒有走列存索引,可通過使用說明進行諮詢或聯絡我們

更多資訊,請參考列存索引常見問題

進階使用

您可以參考以下內容來最佳化列存索引的使用。

進階功能

說明

設定列索引的排序鍵

列存索引資料群組織的基本單位為行組(Row Group)。在每個行組中,不同的列會各自打包形成列資料區塊,這些列資料區塊按照行存未經處理資料的主鍵順序並行構建,整體上呈現無序狀態。您可以通過設定排序鍵來修改列資料區塊的排列順序,以提高查詢效能。

如何對JSON類型進行高效分析

列存索引通過整合列式JSON虛擬列秒級加減列以及列數擴充等一系列相關功能,以應對海量結構化與半結構化資料分析情境。

使用列索引加速ETL

ETL(Extract Transform Load)功能可以讓您在讀寫(RW)節點上使用列存索引,讀寫(RW)節點上的SQL語句中的SELECT請求會發送至列存索引唯讀節點並使用列存索引功能進行加速查詢。讀取資料後,系統會通過內部網路將資料傳回讀寫(RW)節點並寫入目標表。

列存索引唯讀節點開啟Serverless

Serverless功能可以根據業務負載進行自動擴縮容。在高峰時段自動升配,有效應對業務負載的突增。在低穀時段自動降配,有效降低使用成本。

使用Hybrid Plan加速寬表查詢

Hybrid Plan是指在同一條查詢語句中同時使用列式索引和行式索引的查詢方式。Hybrid Plan能夠顯著提高寬表查詢的速度。在執行計畫中,對於適合使用列式索引的部分,將通過列存索引進行執行並擷取中間結果,該中間結果僅包含主鍵資訊。最後,通過主鍵結合InnoDB主索引來查詢需要的所有列資訊並進行輸出。

使用多機MPP對海量資料分析提速

對于海量資料的複雜查詢,單個列存索引唯讀節點已無法滿足效能需求。您可以使用多機並行的方式進行查詢加速。

深入瞭解

如果您對列存索引的原理感興趣,您可以參考以下文檔以深入瞭解列存索引: