本文为您介绍列存索引 CSI 的相关操作。
说明:
对于生产系统而言,开启和创建列存相当于生产变更,需要遵守生产变更流程。为了降低变更风险,TDSQL-C MySQL 版提供了一些验证能力(流量回放),您可以通过 流量回放 来评估列存的使用效果,然后再决定是否在生产系统中开启和创建列存索引。
前提条件
内核版本为 TDSQL-C MySQL 版8.0 3.1.20.001及以上。
说明:
针对只读实例而言,符合版本要求的情况下,4核以上的只读实例才可以开启列存索引功能。
开启或关闭 CSI
说明:
1. 在集群列表页,根据实际使用的视图模式进入实例详情页。
1. 登录 TDSQL-C MySQL 版控制台,在左侧集群列表,单击目标集群,进入集群管理页。
2. 在集群详情下,找到目标实例,单击实例 ID 后的详情,进入实例详情页。
1. 登录 TDSQL-C MySQL 版控制台,在集群列表,找到需要修改字符集的集群,单击集群 ID,进入集群管理页面。
2. 在集群管理页面,选择实例列表页,找到要开启或关闭列存索引的只读实例,单击实例 ID,进入实例详情页。
2. 在实例详情页的实例形态后,单击修改图标。

3. 在弹窗下,选择操作时间,勾选“在操作过程中,会有秒级别闪断,请确保业务具备重连机制”,单击确定。
操作时间
立即执行:立即执行实例形态的切换。
维护时间内:在您设置的实例维护时间内执行,修改维护时间请参见 修改实例维护时间。
说明:
实例形态由行存调整为行列混存,表示开启列存索引 CSI。
实例形态行列混存调整为行存,表示关闭列存索引 CSI。
列存配置
创建和删除 CSI
CREATE TABLE t (c1 INT, c2 INT, c3 INT);INSERT INTO t VALUES (1, 2, 3);
说明:
DDL 需要在 RW 上执行。
创建列存索引支持两种方式:
使用列存注释语法。
使用 COLUMNSTORE 关键字。
推荐使用列存注释语法,原因如下:
COLUMNSTORE 属于新增关键字,现有工具链和生态可能存在兼容性问题。
列存注释默认创建全字段列存索引,字段发生变更时会自动同步,维护成本更低。
若使用 COLUMNSTORE 关键字创建列存索引,则需要手动维护字段列表,字段变更时需同步调整索引定义。
列存注释语法(推荐)
建表时包含列存索引:
-- 列存注释(推荐,全索引)CREATE TABLE t (c1 INT, c2 INT, c3 INT) COMMENT='COLUMNAR=1';
用单独的语句创建列存索引:
-- 列存注释(推荐,全索引)ALTER TABLE t COMMENT 'COLUMNAR=1';
可以通过 SHOW CREATE TABLE table_name FULL 确认表上有没有列存。注意,列存索引使用了新关键字 COLUMNSTORE ,默认不打印以避免影响工具兼容,可以使用 FULL 控制打印。
用列存注释创建的列存索引:
-- SHOW CREATE TABLE t FULLCREATE TABLE `t` (`c1` int DEFAULT NULL,`c2` int DEFAULT NULL,`c3` int DEFAULT NULL,COLUMNSTORE KEY `_default_csi_` (`c1`,`c2`,`c3`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='COLUMNAR=1'
删除索引:
-- 列存注释(推荐)ALTER TABLE t COMMENT 'COLUMNAR=0';
列存关键字语法
注意:
工具生态不一定兼容列存关键字 COLUMNSTORE,而且列存索引字段是固定的,不会自动同步新加字段,因此不建议使用。
建表时包含列存索引:
-- 列存关键字(固定字段索引 csi (c1,c2,c3))CREATE TABLE t (c1 INT, c2 INT, c3 INT, COLUMNSTORE INDEX csi);
用单独的语句创建列存索引:
-- 列存关键字 (固定字段索引 csi (c1,c2,c3))ALTER TABLE t ADD COLUMNSTORE INDEX csi;
删除索引:
-- 列存关键字创建的索引名ALTER TABLE t DROP KEY `csi`;
执行 SQL
EXPLAIN 对于数据表访问会打印 Csi Scan。您可以通过数据库代理接入,满足阈值和兼容检查的 SQL 会自动在列存节点上执行。也可以直连列存 RO 执行 SQL。
-- 小数据量测试设置,生产系统请务必使用有意义的值-- SET columnstore_cost_threshold = 0;-- explain analyze ...-- explain format=tree ...select max(col1) from t1 where col2 < col3;
以下是执行计划打印结果:
| physical_plan -> Ungrouped Aggregate: max(#0)-> Projection: col1 (rows=1)-> Projection: #11 (rows=1)-> Projection: NULL #6 NULL #5 NULL #4 NULL #3 NULL #2 NULL #1 NULL #0 NULL (rows=1)-> Projection: NULL #2 NULL #1 NULL #0 NULL (rows=1)-> Csi Scan Table: test.t1 Projections: col2 col3 col1 (rows=1)
重命名 CSI
开启列存索引 CSI 后,重命名列存索引 CSI 的命令如下:
ALTER TABLE table_name RENAME index old_index_name to new_index_name;
列存索引 CSI HINT 语句
1. 强制执行行存执行/列存执行。
强制执行行存执行
SELECT a FROM t IGNORE INDEX (csi);
强制执行列存执行
SELECT a FROM t FORCE INDEX (csi);
2. 同时使用 HINT 执行并行查询与列存索引。
SELECT /*+PARALLEL(2)*/ a FROM t FORCE INDEX (csi);
创建表和列存索引示例
CREATE TABLE t (a int, columnstore index csi (a));INSERT INTO t VALUES (0), (1), (2);SHOW CREATE TABLE t;SHOW INDEX FROM t;
执行结果如下:
MySQL [test]> CREATE TABLE t (a int, columnstore index csi (a));Query OK, 0 rows affected (0.01 sec)MySQL [test]> INSERT INTO t VALUES (0), (1), (2);Query OK, 3 rows affected (0.01 sec) Records: 3 Duplicates: 0 Warnings: 0MySQL [test]> SHOW CREATE TABLE t;+-------+---------------------------------------------------------------------------------------------------------------+| Table | Create Table |+-------+---------------------------------------------------------------------------------------------------------------+| t | CREATE TABLE `t` ( `a` int DEFAULT NULL, COLUMNSTORE KEY `csi` (`a`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 |+-------+---------------------------------------------------------------------------------------------------------------+MySQL [test]> SHOW INDEX FROM t;+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+-------------+---------+---------------+---------+------------+| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+-------------+---------+---------------+---------+------------+| t | 1 | csi | 1 | a | NULL | 1 | NULL | NULL | YES | COLUMNSTORE | | | YES | NULL |+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+-------------+---------+---------------+---------+------------+1 row in set (0.00 sec)
INDEX HINT 使用
1. 强制语句使用列存索引。
SELECT a FROM t FORCE INDEX (csi);EXPLAIN FORMAT=TREE SELECT a FROM t FORCE INDEX (csi);
执行结果:
MySQL [test]> SELECT a FROM t FORCE INDEX (csi);+------+| a |+------+| 0 || 1 || 2 |+------+3 rows in set (0.00 sec)MySQL [test]> EXPLAIN FORMAT=TREE SELECT a FROM t FORCE INDEX (csi);+---------------------------------------------------------------+| EXPLAIN |+---------------------------------------------------------------+| -> COLUMNSTORE Index scan on t using csi (cost=1.30 rows=3) |+---------------------------------------------------------------+1 row in set (0.00 sec)
2. 强制语句不使用列存索引(行存执行)。
SELECT a FROM t IGNORE INDEX (csi);EXPLAIN FORMAT=TREE SELECT a FROM t IGNORE INDEX (csi);
执行结果:
MySQL [test]> SELECT a FROM t IGNORE INDEX (csi);+------+| a |+------+| 0 || 1 || 2 |+------+3 rows in set (0.00 sec)MySQL [test]> EXPLAIN FORMAT=TREE SELECT a FROM t IGNORE INDEX (csi);+-----------------------------------------+| EXPLAIN |+-----------------------------------------+| -> Table scan on t (cost=0.55 rows=3) |+-----------------------------------------+1 row in set (0.00 sec)
查看 CSI 索引创建情况
show create table TABLE
说明:
默认不显示 COLUMNSTORE 前缀,需要指定开关 columnstore_display_in_show_create=1,才会显示。
show index from TABLE
explain format=tree
说明:
开启 CSI 后,要查看 CSI 索引创建情况,也可通过 explain format=tree 查看执行计划算子是否有 COLUMNSTORE 前缀(有则表示算子采用了列式执行),来得知该算子是否使用列式执行。只有指定 format=tree 时,才显示 COLUMNSTORE 前缀,不指定格式则默认不显示 COLUMNSTORE。