You can enable and use the In-Memory Column Index (IMCI) feature for PolarDB for PostgreSQL in two ways: by adding an IMCI read-only node or by using the pre-installed extension. Choose the method that best suits your needs.
Prerequisites
-
Cluster versions:
-
PostgreSQL 14 (minor engine version 2.0.14.10.20.0 or later)
-
PostgreSQL 15 (minor engine version 2.0.15.15.7.0 or later)
-
PostgreSQL 16 (minor engine version 2.0.16.8.3.0 or later)
-
PostgreSQL 17 (minor engine version 2.0.17.7.5.0 or later)
NoteYou can view the minor engine version in the console or by running the
SHOW polardb_version;statement. If your cluster does not meet the requirement, you must upgrade the minor engine version. -
-
The
wal_levelparameter must be set tological. This setting adds the required information for logical decoding to the write-ahead logging (WAL).NoteYou can set the wal_level parameter in the console. Modifying this parameter restarts the cluster. Plan your business operations accordingly and proceed with caution.
-
The source table must have a primary key, and the primary key column must be included when you create the columnstore index. Using a
SERIALorBIGSERIALdata type for the primary key is recommended, as it significantly improves data synchronization efficiency. -
You can create only one columnstore index for each table.
Enable the IMCI feature
The method for enabling IMCI varies depending on the minor engine version of your PolarDB for PostgreSQL cluster:
Create a columnstore index
1. Create a columnstore index
Syntax
-- Create an index for specific columns
CREATE INDEX [ CONCURRENTLY ] csi_index_name ON table_name USING CSI(column1,column2,...);
-- Create an index for all columns
CREATE INDEX [ CONCURRENTLY ] csi_index_name ON table_name USING CSI;
Parameters
|
Parameter |
Description |
|
CONCURRENTLY |
Optional. Creates the index concurrently, which avoids blocking write operations on the source table. This method is ideal for creating an index on a live table. Note
|
|
csi_index_name |
The custom name of the columnstore index. |
|
table_name |
The name of the table for which to create the columnstore index. |
|
column1,column2,... |
The columns to include in the columnstore index. If no columns are specified, the index is created on all columns of the table. |
Example
-
Create a sample table named
sales.CREATE TABLE sales (sale_id int primary key, name CHAR(10), amount int); -
Since a table can have only one columnstore index, run one of the following statements.
Specific columns
CREATE INDEX idx_csi_sales ON sales USING CSI(sale_id, amount);All columns
CREATE INDEX idx_csi_sales ON sales USING CSI;Concurrent mode
Creating an index concurrently does not block write operations on the source table. This method is ideal for creating an index on a live table.
CREATE INDEX CONCURRENTLY idx_csi_sales ON sales USING CSI(sale_id, amount);After the index is created, you can run the following statement to view the index information:
SELECT * FROM pg_indexes WHERE tablename = 'sales';
2. View index progress
Creating a columnstore index on a large table can be time-consuming. You can monitor the progress with the following query. You can also adjust relevant parameters to improve the index creation speed.
SELECT * FROM pg_stat_progress_create_index;
3. (Optional) Cancel index creation
If creating an index takes a long time and the process affects your services, you can use pg_cancel_backend or pg_terminate_backend to cancel the index creation. Obtain the required pid as described in Step 2. View the index creation progress.
SELECT pg_cancel_backend(pid);
SELECT pg_terminate_backend(pid);
4. View the index size
Use the pg_relation_size function to view the index size. You can combine it with the pg_size_pretty function to display the size in a more readable format.
SELECT * FROM pg_size_pretty(pg_relation_size('csi_index_name'));
For example, view the storage space occupied by the previously created columnstore index.
SELECT * FROM pg_size_pretty(pg_relation_size('idx_csi_sales'));
5. (Optional) Real-time data synchronization
PolarDB for PostgreSQL clusters not only support creating columnstore indexes on historical data but also automatically synchronize new data from the row store table to the columnstore index. After you use the CREATE INDEX statement to create a columnstore index for a table, new data is written to the columnstore index in real time, and no extra operations are required.
IMCI uses the logical replication mechanism of PolarDB for PostgreSQL to synchronize data by decoding WAL logs and applying the changes to the columnstore engine. With the default configuration, this mechanism can handle a write throughput of approximately 200,000 QPS (based on the Sysbench oltp_insert standard test).
-
Check the current data synchronization latency
SELECT active_pid, database, slot_name, pg_size_pretty(pg_current_wal_lsn() - confirmed_flush_lsn) AS size FROM pg_replication_slots WHERE slot_name LIKE 'csi_sync_%';If the
sizeremains within 50 MB, the columnstore data is typically refreshed within seconds. -
Improve data synchronization efficiency
To meet the real-time requirements for row-store and column-store data in certain business scenarios, you can adjust the
polar_csi.update_intervalandpolar_csi.update_batch_countparameters to improve the real-time performance of the columnstore index.
Use IMCI
1. Configure parameters
After you create a columnstore index, you can use the following parameters to control whether SQL queries use the columnstore index.
|
Parameter |
Description |
|
polar_csi.enable_query |
Specifies whether to allow queries to use the columnstore index. Valid values:
|
|
polar_csi.cost_threshold |
If a query's estimated cost exceeds this threshold, the optimizer chooses the columnstore engine; otherwise, it uses the row store engine.
Note
If you set this parameter to 0, all queries prioritize using the columnstore index. Avoid setting this value to 0 in a production environment. Adjust this value dynamically based on the load on the row store and columnstore engines. |
2. Configure the parameter scope
Global scope
You can use the console to set the polar_csi.enable_query parameter to on. This allows queries in all databases to attempt to use the columnstore index.
Session scope
All queries within the session attempt to use the columnstore index.
SET polar_csi.enable_query = ON;
Statement scope
A single SQL query within a session can use the columnstore index with a hint.
Because this feature depends on the pg_hint_plan extension, you must execute CREATE EXTENSION pg_hint_plan; in the target database to install it.
-
Set only
polar_csi.enable_query.-- Allow the query to use the columnstore index /*+ SET (polar_csi.enable_query on) */ SELECT COUNT(*) FROM sales; -
Set
polar_csi.enable_queryandpolar_csi.cost_threshold.-- Allow the query to use the columnstore index and set the query cost threshold to 0 /*+SET (polar_csi.enable_query on) SET(polar_csi.cost_threshold 0)*/ SELECT COUNT(*) FROM sales;
3. Check for index usage
You can use EXPLAIN or EXPLAIN ANALYZE to view the query plan. If the plan includes the CSI Executor keyword, it indicates the query used the columnstore index.
EXPLAIN SELECT COUNT(*) FROM sales;
The following result is returned:
QUERY PLAN
--------------
CSI Executor
(1 row)
4. (Optional) Configure IMCI query consistency
The IMCI feature in PolarDB for PostgreSQL offers two query consistency levels to suit different business needs.
-
Eventual consistency (default): Suitable for write-intensive workloads with low real-time data requirements.
-
Strong consistency: Ensures query results are returned only after the data in the column store is fully consistent with the data in the row store.
Data synchronization for IMCI in PolarDB for PostgreSQL typically has a latency on the order of seconds. However, data latency increases under heavy write loads. The default consistency level is eventual consistency. Therefore, if the write load is high and a SQL query uses the columnstore index, the query might not retrieve the latest data.
For business scenarios that require strong consistency between row-store and column-store data, you can set the polar_csi.forward_replay_wait parameter to on. This enables strong consistency reads. When a query runs, it waits until the columnstore index data is consistent with the row-store data before execution.
Delete and rebuild a columnstore index
PolarDB for PostgreSQL does not support modifying columnstore indexes. To add columns to an index, you must delete and then recreate it.
Delete index
Syntax
DROP INDEX csi_index_name;
Parameters
|
Parameter |
Description |
|
csi_index_name |
The name of the columnstore index to delete. |
Example
Delete the previously created columnstore index.
DROP INDEX idx_csi_sales;
Rebuild index
Syntax
REINDEX INDEX csi_index_name;
Parameters
|
Parameter |
Description |
|
csi_index_name |
The name of the columnstore index to rebuild. |
Example
Rebuild the previously created columnstore index.
REINDEX INDEX idx_csi_sales;
Tune IMCI parameters
Improve index creation speed
The index creation speed depends on the following parameters:
|
Parameter |
Value range |
Default |
Description |
|
polar_csi.memory_limit |
1–1048576 |
4096 |
The amount of memory that the columnstore index can use, in MB. A larger memory limit results in faster index creation. Adjust this parameter based on your cluster specifications. We recommend that you do not set this value to more than 25% of the cluster memory to avoid the risk of out-of-memory (OOM) errors. Note
|
|
polar_csi.flush_count |
2048–20480000 |
204800 |
The number of rows in a batch commit when creating an index. Increasing this value can improve creation efficiency but also increases memory consumption. |
Improve real-time performance
By adjusting the following parameters, you can increase the speed of row-to-column transformation and improve the real-time performance of columnstore index data.
|
Parameter |
Value range |
Default |
Description |
|
polar_csi.update_interval |
0–3600 |
1 |
The interval for periodic updates of real-time data for row and column stores, in seconds. Increasing the update interval can merge small transactions of the same type, which improves data update efficiency when there are many transactions. Note
|
|
polar_csi.update_batch_count |
1024–4294967295 |
100000 |
The threshold for the number of rows in a batch update. This is the maximum number of rows in an update transaction. Increasing this threshold can improve data update efficiency. Note
|
Improve query speed
Query performance primarily depends on the following parameters. You can adjust their values to improve query performance:
|
Parameter |
Value range |
Default |
Description |
|
polar_csi.exec_parallel |
1–512 |
2 |
The degree of parallelism for a columnstore index, which is the number of CPU cores a single SQL statement can use. In general, a higher degree of parallelism results in better performance. The actual value depends on the cluster specifications. Adjust this parameter based on your cluster specifications. We recommend that you do not set this value higher than the number of CPU cores of the compute node. |
|
polar_csi.memory_limit |
1–1048576 |
4096 |
The amount of memory that the columnstore index can use, in MB. A larger memory limit results in faster index creation. Adjust this parameter based on your cluster specifications. We recommend that you do not set this value to more than 25% of the cluster memory to avoid the risk of OOM errors. Note
|
|
polar_csi.cost_threshold |
1–1000000000 |
50000 |
When the query cost is less than this threshold, the query does not use the columnstore index for acceleration. Adjust this value based on your business load.
Note
|
|
polar_csi.forward_replay_wait |
on|off |
off |
The IMCI query consistency level. Valid values:
|