CREATE TABLE [IF NOT EXISTS] [database.]table_name (column_definition1[, column_definition2, ...]) ENGINE = ROW_STORE PRIMARY KEY(column1[, column2]);
行存建表语句和普通StarRocks表相似, 主要通过`ENGINE = ROW_STORE`来指明是否为行存表.
column_definition参数说明:
col_name col_type [NULL | NOT NULL] [DEFAULT "default_value"]
其中:
col_name:列名称
col_type:列数据类型
支持的列类型信息如下:
类型 | 描述 | 说明 |
---|---|---|
整型类 | INT、LARGEINT | 用于主键Key和Value字段 |
TINYINT、SMALLINT、BIGINT | 仅用于Value字段 | |
浮点类 | FLOAT、DOUBLE、DECIMAL | 仅用于Value字段 |
日期类 | DATE | 用于主键Key和Value字段 |
DATETIME | 仅用于Value字段 | |
字符串类 | VARCHAR | 用于主键Key和Value字段 |
CHAR | 仅用于Value字段 | |
Boolean类型 | BOOLEAN | 用于主键Key和Value字段 |
说明
DROP TABLE [IF EXISTS] [database.]table_name [FORCE]
行存表的删除,不支持回收站功能,因此执行删除表的SQL后,会清除对应的数据,且无法恢复。
在SQL语句中指定FORCE
会等待数据删除完才会结束; 不指定FORCE
,则采用异步删除逻辑。
-- 添加列 ALTER TABLE [database.]table ADD COLUMN column_name column_type [DEFAULT "default_value"] -- 表重名名 ALTER TABLE table_name RENAME new_table_name;
行存表的数据变更行为与列存表不一样,列存表数据变更的时候会重写数据,而行存表并不会重写数据,因此行存表的数据变更非常快。
目前行存表的数据变更只支持两种动作:添加列以及修改表名,添加列也仅只支持在最后一列添加新列。
列存表的一些高级能力,例如二级索引和物化视图等能力,目前在行存表中并未支持,因此Index和Materialed View相关的语法也都未支持。
行存表询语法基本上同列存表。列存表的相关语法参考StarRocks社区。
对于行存表,使用全主键进行查询时,会走短路径对SQL进行优化。
示例
-- 创建表 CREATE DATABASE IF NOT EXISTS demo; DROP TABLE IF EXISTS demo.t1; CREATE TABLE IF NOT EXISTS demo.t1 ( k1 int, k2 varchar(16), v1 varchar(16) DEFAULT '1', v2 DATE NOT NULL DEFAULT '2222-12-12' COMMENT "YYYY-MM-DD", v3 TINYINT DEFAULT '0' COMMENT "range [-128, 127]") ENGINE=ROW_STORE PRIMARY KEY (k1, k2); --插入数据 INSERT INTO demo.t1(k1, k2, v1, v2, v3) VALUES (1, '1', 'a', '2222-10-23', 31); INSERT INTO demo.t1(k1, k2, v1, v2, v3) VALUES (1, '2', 'b', '2222-10-24', 32); INSERT INTO demo.t1(k1, k2, v1, v2, v3) VALUES (1, '3', 'c', '2222-10-25', 33); INSERT INTO demo.t1(k1, k2, v1, v2, v3) VALUES (2, '4', 'd', '2222-10-26', 34); -- 多主键查询: 主键(k1, k2) SELECT * FROM demo.t1 WHERE k1 = 1 AND k2 = '1'; SELECT * FROM demo.t1 WHERE k1 = 1 AND k2 IN ('1', '2'); -- 通过EXPLAIN查看执行计划,从执行计划可以判断是否走短路读 EXPLAIN SELECT * FROM demo.t1 WHERE k1 = 1 AND k2 IN ('1', '2'); --关闭短路读写能力,查看SQL执行计划 SET enable_short_circuit = false; EXPLAIN SELECT * FROM demo.t1 WHERE k1 = 1 AND k2 IN ('1', '2'); --开启短路读写能力 SET enable_short_circuit = true;
在行存表中,对于主键的范围查询也进行了优化,根据主键的范围,计算数据的扫描范围,减少数据的摄取量。
示例
以多主键范围查询为例,也适合于单一主键范围查询。
-- 多主键范围查询: 主键(k1, k2, k3) SELECT * FROM demo.t1 WHERE k1 = 1 and k2 <= '4'; SELECT * FROM demo.t1 WHERE k1 >= 1 and k2 <= '4'; SELECT * FROM demo.t1 WHERE k1 >= 1 and k2 <= '4' and k2 > '2';
行存表查询时,也支持非主键的查询功能。
示例
-- 非主键查询 SELECT sum(v3) FROM demo.t1 WHERE v1 = 'a'; SELECT v2 FROM demo.t1 WHERE v1 = 'a' and v3 > 30;
注意
行存表支持全表扫描, 但全表扫描的效率是远远低于列存表的,在数据量大的情况下,容易出现查询超时,因此需要尽量避免行存表出现全表扫描。
行存表中支持插入、更新、删除操作,语法基本上同列存表。列存表的相关语法参考StarRocks社区。
-- 支持Insert values INSERT INTO demo.t1(k1, k2, v1, v2, v3) VALUES (3, '5', 'e', '2222-12-22', 34); -- 支持Partial insert, 字段列表必须包含全部主键列, 未指明的列会填入默认值或者设置null INSERT INTO demo.t1(k1, k2, v1) VALUES (4, '6', 'f'),(5, '7', 'g'); -- 支持insert ignore语法, 当出现主键冲突时, 忽略新值, 保留旧值 INSERT IGNORE INTO demo.t1 VALUES (4, '6', 'f1','2222-12-22', 12),(5, '7', 'g1','2222-12-22', 13); INSERT IGNORE INTO demo.t1(k1, k2, v1) VALUES (4, '6', 'f1'),(5, '7', 'g1'); -- 支持insert duplicate语法, 当出现主键冲突时, 能够按照语法赋值 --- partial insert and upsert INSERT INTO demo.t1 (k1, k2, v1) VALUES (4, '6', 'f2') AS v ON DUPLICATE KEY UPDATE v1 = v.v1; --- 常量赋值 INSERT INTO demo.t1 (k1, k2, v1) VALUES (4, '6', 'v1_new') AS v ON DUPLICATE key UPDATE v1 = 'x'; --- 表达式计算 INSERT INTO demo.t1 (k1, k2, v3) VALUES (4, '6', 10) AS v ON DUPLICATE key UPDATE v3 = v.v3 + 1; --- 使用旧值进行表达式计算 INSERT INTO demo.t1 (k1, k2, v3) VALUES (4, '6', 10) AS v ON DUPLICATE key UPDATE v3 = t1.v3 + 1; -- 支持Insert select CREATE TABLE IF NOT EXISTS demo.t1_copy ( k1 int, k2 varchar(16), v1 varchar(16) DEFAULT '3', v2 DATE NOT NULL DEFAULT '2222-12-12' COMMENT "YYYY-MM-DD", v3 TINYINT DEFAULT '0' COMMENT "range [-128, 127]") ENGINE=ROW_STORE PRIMARY KEY (k1, k2); INSERT INTO demo.t1_copy SELECT * FROM demo.t1;
注意
行存表的插入默认语义与列存表保持一致, 默认为upsert语法, 插入时并不检查主键唯一性, 如果主键相同, 则新写入的值覆盖旧值.
-- 主键点更新 UPDATE demo.t1 SET v1 = 'value1_new' WHERE k1 = 3 AND k2 = '5'; -- 主键范围更新 UPDATE demo.t1 SET v1 = 'value1_new_2' WHERE k1 = 1 AND k2 > '1' AND k2 <= '5'; -- 非主键大范围更新 UPDATE demo.t1 SET v1 = 'value1_new_3' WHERE v3 > 30 AND v3 < 32; -- 支持表达式计算 UPDATE demo.t1 SET v3 = v3 + 1 WHERE k1 = 1;
注意
行存表不支持更新时修改主键的值。
-- 主键点删除 DELETE FROM demo.t1 WHERE k1 = 3 AND k2 = '5'; -- 主键范围删除 DELETE FROM demo.t1 WHERE k1 = 1 AND k2 > '1' AND k2 <= '5'; -- 非主键删除 DELETE FROM demo.t1 WHERE v3 > 30 AND v3 < 32;
查询表结构及建表语句
-- 查询表字段属性 DESC demo.t1; -- 展示建表语句 SHOW CREATE TABLE demo.t1;
查询表大小
SHOW DATA FROM demo.t1;
注意
行存表为了性能, 没有对存储大小进行精确统计,使用Show data返回实际数据的近似值。
行存表参数配置都是Session级参数, 可以通过SET系统变量方式修改配置项的数值
配置项 | 默认值 | 说明 | 用户参数 |
---|---|---|---|
enable_short_circuit | true | 短路读写的开关 | 文档呈现 |
enable_row_store_update_atomic | true | 行存表更新时, 使用CAS检验原值, 防止行级LostUpdate事务异常出现 | 文档呈现 |
enable_audit_execute_stmt | false | Preparestmt的执行默认不打印audit日志, 如果需要打印日志, 打开该配置项 | 隐藏 |
enable_row_store_runtime_filter | true | 行存表的RuntimeFilter开关参数 | 隐藏 |
enable_row_store_push_down_limit | true | 行存表支持LIMIT的下推开关 | 隐藏 |
enable_row_store_push_down_topn | true | 行存表支持TOPN的下推开关 | 隐藏 |
--创建行存表 CREATE DATABASE IF NOT EXISTS demo; DROP TABLE IF EXISTS demo.t1; CREATE TABLE IF NOT EXISTS demo.t1( k1 int, k2 int, v1 varchar(16), v2 DATE NOT NULL COMMENT "YYYY-MM-DD", v3 TINYINT COMMENT "range [-128, 127]" ) ENGINE=ROW_STORE PRIMARY KEY (k1, k2); --插入 INSERT INTO demo.t1(k1, k2, v1, v2, v3) VALUES (1, 2, 'a', "2222-12-22", 33), (1, 3, 'b', "2222-12-22", 34), (1, 4, 'c', "2222-12-22", 35), (2, 2, 'd', "2222-12-22", 36), (2, 3, 'd', "2222-12-22", 37), (3, 3, 'e', "2222-12-22", 100), (4, 4, 'f', "2222-12-22", 101); --查询 SELECT count(*) FROM demo.t1; SELECT * FROM demo.t1 limit 3; SELECT k2, sum(k1) FROM demo.t1 group by k2; --更新 update demo.t1 set v1 = '5' where k1 = 3 and k2 = 3; select * from demo.t1 where k1 = 3 and k2 = 3; --删除数据 DELETE FROM demo.t1 WHERE k1 = 1 and k2 = 2; select * from demo.t1 WHERE k1 = 1 and k2 = 2; DELETE FROM demo.t1 WHERE k1 = 1; select * from demo.t1 WHERE k1 = 1; --清空 TRUNCATE TABLE demo.t1; --drop表 DROP TABLE demo.t1 FORCE;
步骤一:创建行存表
CREATE DATABASE IF NOT EXISTS demo; CREATE TABLE IF NOT EXISTS demo.tbl_point_query( `k1` int(11), `v1` varchar(30) NULL, `v2` decimal(27, 9) NULL ) ENGINE=ROW_STORE PRIMARY KEY (k1);
步骤二:采用Java程序使用PreparedStatement
public static void main(String[] args) throws Exception { // 设置 JDBC url,并在 Server 端开启 prepared statement String mysqlUrl = "jdbc:mysql://${FE地址}:9030/?useServerPrepStmts=true"; String mysqlUser = "${mysqlUser}"; String mysqlPassword = "${mysqlPassword}"; DriverManager.registerDriver(((java.sql.Driver) Class.forName("com.mysql.cj.jdbc.Driver").getDeclaredConstructor().newInstance())); Connection conn = DriverManager.getConnection(mysqlUrl, mysqlUser, mysqlPassword); // use `?` for placement holders String insertSql = "INSERT INTO demo.tbl_point_query VALUES(?,?,?)"; PreparedStatement insertPstmt = conn.prepareStatement(insertSql); insertPstmt.setInt(1, 1); insertPstmt.setString(2, "v1"); insertPstmt.setBigDecimal(3, new BigDecimal("123456.12")); insertPstmt.execute(); // use `?` for placement holders String selectSql = "SELECT * FROM demo.tbl_point_query where k1 = ?"; PreparedStatement selectPstmt = conn.prepareStatement(selectSql); selectPstmt.setInt(1, 1); ResultSet rs = selectPstmt.executeQuery(); while (rs.next()) { System.out.println(String.format("The value of k1: %s, the value of v1: %s,the value of v2: %s", rs.getInt(1),rs.getString(2), rs.getBigDecimal(3))); } }
说明
用例中${FE地址}、${mysqlUser}、${mysqlPassword}需要根据实际环境替换
如果您使用的是maven工程,需要在pom.xml文件引入mysql依赖:
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.28</version> </dependency>