本文将介绍如何创建并使用列存索引功能。
注意事项
实例版本需为5.4.19-16989811及以上。
仅企业版的主实例支持列存索引的
CREATE
语法,在只读实例上仅支持SHOW INDEX
等查询命令。
创建CCI相关的约束
不支持通过任何方式使用前缀索引。
创建CCI时必须指定索引名。
创建CCI默认包含主表上的所有列,不需要额外指定,不支持调整。
创建CCI不会额外创建任何局部索引。
索引定义中,排序键的
length
参数将被忽略。
目前的版本中,CCI数据类型和主表的DDL具有一定限制,具体可参见使用限制。
语法
PolarDB-X对MySQL DDL语法进行了扩展,增加定义CCI的语法,使用方式与在MySQL上创建索引一致。
CLUSTERED COLUMNAR:关键字,用于指定添加的索引类型为CCI。
索引名:索引表的名称,用于在SQL语句中指定该索引。
排序键:索引的排序键,即数据在索引文件中按照该列有序存储。
索引分区子句:索引的分区算法,与
CREATE TABLE
中分区子句的语法一致。
CREATE
CLUSTERED COLUMNAR INDEX index_name
ON tbl_name (index_sort_key_name,...)
[partition_options]
# 分区策略定义
partition_options:
PARTITION BY
HASH({column_name | partition_func(column_name)})
| KEY(column_list)
| RANGE({column_name | partition_func(column_name)})
| RANGE COLUMNS(column_list)
| LIST({column_name | partition_func(column_name)})
| LIST COLUMNS(column_list)} }
partition_list_spec
# 分区函数定义
partition_func:
YEAR
| TO_DAYS
| TO_SECOND
| UNIX_TIMESTAMP
| MONTH
# 分区列表定义
partition_list_spec:
hash_partition_list
| range_partition_list
| list_partition_list
# Hash/Key分区表列定义
hash_partition_list:
PARTITIONS partition_count
# Range/Range Columns分区表列定义
range_partition_list:
range_partition [, range_partition ...]
range_partition:
PARTITION partition_name VALUES LESS THAN {(expr | value_list)} [partition_spec_options]
# List/List Columns分区表列定义
list_partition_list:
list_partition [, list_partition ...]
list_partition:
PARTITION partition_name VALUES IN (value_list) [partition_spec_options]
示例
# 先创建表
CREATE TABLE t_order (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`order_id` varchar(20) DEFAULT NULL,
`buyer_id` varchar(20) DEFAULT NULL,
`seller_id` varchar(20) DEFAULT NULL,
`order_snapshot` longtext DEFAULT NULL,
`order_detail` longtext DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `l_i_order` (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 partition by hash(`order_id`) partitions 16;
# 再创建列存索引
CREATE CLUSTERED COLUMNAR INDEX `cc_i_seller` ON t_order (`seller_id`) partition by hash(`order_id`) partitions 16;
主表:"t_order" 是分区表,分区的拆分方式为按照 "order_id" 列进行哈希。
列存索引:"cc_i_seller" 按照 "seller_id" 列进行排序,按照 "order_id" 列进行哈希。
索引定义子句:
CLUSTERED COLUMNAR INDEX `cc_i_seller` ON t_order (`seller_id`) partition by hash(`order_id`) partitions 16
。
使用CCI
CCI创建完成后,可以通过如下方式指定查询使用的索引表:
通过HINT指定索引
您可以选择以下HINT语句,指定使用目标索引进行查询。
FORCE INDEX({index_name})
示例:
SELECT a.*, b.order_id FROM t_seller a JOIN t_order b FORCE INDEX(cc_i_seller) ON a.seller_id = b.seller_id WHERE a.seller_nick="abc";
索引选择
对于带有列存索引的主表查询,PolarDB-X会自动选择出优化器认为代价最低的索引表(目前仅支持在只读实例上查询列存索引)。
IGNORE INDEX与USE INDEX
通过以下HINT可以指定优化器不使用某些索引。
IGNORE INDEX({index_name},...)
示例:
SELECT t_order.id,t_order.order_snapshot FROM t_order IGNORE INDEX(cc_i_seller) WHERE t_order.seller_id = 's1';
通过以下HINT可以指定使用某索引。
USE INDEX({index_name},...)
示例:
SELECT t_order.id,t_order.order_snapshot FROM t_order USE INDEX(cc_i_seller) WHERE t_order.seller_id = 's1';
使用限制
创建CCI时,主键、排序键和分区键的数据类型具有一定限制。
在包含CCI的表中,执行DDL具有一定限制,目前仅支持常见的DDL语句。
执行DDL变更列数据类型时,支持有限的数据类型。
开关
您可以通过下面的参数控制是否允许在包含 CCI 的表中执行 DDL,参数默认关闭。
SET [GLOBAL] forbid_ddl_with_cci = [true | false]
数据类型限制
CCI中不同列数据类型的支持情况。
数据类型 | 主键 | 排序键 | 分区键 | |
数值类型 | BIT (UNSIGNED) | 支持 | 支持 | 不支持 |
TINYINT (UNSIGNED) | 支持 | 支持 | 支持 | |
SMALLINT (UNSIGNED) | 支持 | 支持 | 支持 | |
MEDIUMINT (UNSIGNED) | 支持 | 支持 | 支持 | |
INT (UNSIGNED) | 支持 | 支持 | 支持 | |
BIGINT (UNSIGNED) | 支持 | 支持 | 支持 | |
时间类型 | DATE | 支持 | 支持 | 支持 |
DATETIME | 支持 | 支持 | 支持 | |
TIMESTAMP | 支持 | 支持 | 支持 | |
TIME | 支持 | 支持 | 不支持 | |
YEAR | 支持 | 支持 | 不支持 | |
字符串类型 | CHAR | 支持 | 支持 | 支持 |
VARCHAR | 支持 | 支持 | 支持 | |
TEXT | 支持 | 支持 | 不支持 | |
BINARY | 支持 | 支持 | 支持 | |
VARBINARY | 支持 | 支持 | 支持 | |
BLOB | 支持 | 支持 | 不支持 | |
浮点数类型 | FLOAT | 不支持 | 不支持 | 不支持 |
DOUBLE | 不支持 | 不支持 | 不支持 | |
DECIMAL | 不支持 | 不支持 | 不支持 | |
NUMERIC | 不支持 | 不支持 | 不支持 | |
特殊类型 | JSON | 不支持 | 不支持 | 不支持 |
ENUM | 不支持 | 不支持 | 不支持 | |
SET | 不支持 | 不支持 | 不支持 | |
POINT | 不支持 | 不支持 | 不支持 | |
GEOMETRY | 不支持 | 不支持 | 不支持 |
CCI分区键类型支持与CN基本一致,详见数据类型说明。
DDL语句限制
ALTER TABLE 相关约束
语句
是否支持变更主表分区键
是否支持变更主键
是否支持变更索引分区键
是否支持变更排序键
ADD COLUMN
不涉及
不支持
不涉及
不涉及
ALTER COLUMN SET DEFAULT、ALTER COLUMN DROP DEFAULT
不支持
不支持
不支持
不支持
CHANGE COLUMN
不支持
不支持
不支持
不支持
DROP COLUMN
不支持
不支持
不支持
不支持
MODIFY COLUMN
不支持
不支持
不支持
不支持
说明目前支持在包含CCI的表上执行列变更相关的ALTER TABLE语句,不支持对主键、主表/索引分区键、排序键的变更,支持对其他列的变更。暂不支持在ALTER TABLE中变更多个列,您可以将多个ALTER TABLE子句拆分后执行。
MODIFY/CHANGE COLUMN 类型限制
支持类型
不支持类型
数值类型:BIT (UNSIGNED),TINYINT (UNSIGNED),SMALLINT (UNSIGNED),MEDIUMINT (UNSIGNED),INT (UNSIGNED),BIGINT (UNSIGNED)
时间类型:DATETIME
浮点数类型:FLOAT,DOUBLE,DECIMAL、NUMERIC
字符串类型:CHAR,VARCHAR
字符串类型:TEXT,BINARY,VARBINARY,BLOB。
时间类型:TIMESTAMP、TIME、YEAR。
特殊类型:JSON、ENUM、SET、POINT、GEOMETRY。
说明通过ALTER TABLE CHANGE/MODIFY COLUMN 变更列类型时,具有一定的限制。如果遇到不支持的类型,您可以先使用DROP INDEX删除列存索引,变更列类型后再重新创建新的列存索引。
ALTER TABLE 语句变更索引的支持情况
语句
是否支持
ALTER TABLE ADD PRIMARY KEY
支持
ALTER TABLE ADD [UNIQUE/FULLTEXT/SPATIAL/FOREIGN] KEY
支持
ALTER TABLE DROP INDEX
支持
ALTER TABLE DROP FOREIGN KEY fk_symbol
支持
ALTER TABLE DROP PRIMARY KEY
禁止
ALTER TABLE ALTER INDEX index_name {VISIBLE | INVISIBLE}
不支持修改CCI
ALTER TABLE {DISABLE | ENABLE} KEYS
不支持修改CCI
ALTER TABLE RENAME INDEX
不支持修改CCI
说明目前禁止直接使用RENAME INDEX命令重命名列存索引。如需修改列存索引名,您可以先使用DROP INDEX删除对应的列存索引,再重新创建一个新的列存索引。
包含CCI的表上执行其他DDL时的约束
语句
是否支持
DROP TABLE
支持
DROP INDEX
支持
RENAME TABLE
支持
ALTER TABLE RENAME
支持
TRUNCATE TABLE
不支持
说明考虑主表与列存索引的数据一致性,目前禁止执行TRUNCATE TABLE语句。如需清空主表与列存索引数据,您可以使用DELETE语句删除对应的数据。
常见问题
创建列存索引时能否不指定排序键(index_sort_key_name)?
答:不能。必须在
CREATE CLUSTERED COLUMNAR INDEX
语句中显式指定排序键。排序键与分区键可以是完全不同的列。例如在 "t_order" 表上创建CCI时,可以指定 "seller_id" 作为排序键,"order_id" 作为分区键。
创建列存索引时能否不指定分区键?
答:可以。如果没有指定分区键,则默认选择主键作为分区键,选择HASH作为分区策略。
如何查看创建列存索引的进度?
答:可以通过SHOW COLUMNAR INDEX查看列存索引当前的状态,通过SHOW DDL查看DDL任务的执行进度。
如何删除列存索引?
答:可以通过DROP INDEX删除已经成功创建的列存索引。