SQL语句
所有文档
menu
没有找到结果,请重新输入

PALO

SQL语句

DDL语句

Create Database

该语句用于新建数据库(database)

语法:

CREATE DATABASE [IF NOT EXISTS] db_name;

举例:

新建数据库 db_test
CREATE DATABASE db_test;

Create Table

该语句用于创建表(table)

语法:

CREATE [EXTERNAL] TABLE [IF NOT EXISTS] [database.]table_name
 (column_definition[, column_definition, ...]) 
 [ENGINE = [olap|mysql|broker]]
 [key_desc]   
 [partition_desc]    
 [distribution_desc]    
 [PROPERTIES ("key"="value", ...)]
 [BROKER PROPERTIES ("key"="value", ...)];

Column_definition

语法:

col_name col_type [agg_type] [NULL | NOT NULL] [DEFAULT "default_value"]
  • col_name:列名称
  • col_type:列类型,可以是INT,DOUBLE,DATE等,参考数据类型章节。
  • agg_type:聚合类型,目前支持SUM,MAX,MIN、REPLACE和HLL_UNION(仅用于HLL列,为HLL独有的聚合方式)5种。聚合类型是可选选项,如果不指定,说明该列是维度列(key列),否则是事实列(value列)。建表语句中,所有的key列必须在value列之前,一张表可以没有value列,这样的表就是维度表,但不能没有key列。该类型只对聚合模型(key_desc的type为AGGREGATE KEY)有用,其它模型不需要指定这个。
  • 是否允许为NULL: 默认允许为NULL,导入时用\N来表示

说明:

在导入的时候,Doris会自动把相同key列对应的value列按照指定的聚合方法合并(针对聚合模型)。比如,Doris中有一张表包含三列:k1,k2和v,其中v是int类型的value列,聚合方法是SUM,k1和k2是key列。假如原本有数据如下

 | k1  | k2  | v   |
 |-----|-----|-----|
 | 1   | 1   | 10  |
 | 1   | 2   | 20  |
 | 2   | 2   | 30  |

新导入的数据如下:

 | k1  | k2  | v   |
 |-----|-----|-----|
 | 1   | 1   | 5   |
 | 2   | 2   | 10  |
 | 3   | 1   | 5   |

导入以后,Doris中的数据如下

 | k1  | k2  | v   |
 |-----|-----|-----|
 | 1   | 1   | 15  |
 | 1   | 2   | 20  |
 | 2   | 2   | 40  |
 | 3   | 1   | 5   |

可以看到,在k1和k2相同的时候,v列使用SUM聚合方法做了聚合。

ENGINE类型

说明:

ENGINE默认为olap,也就是由Doris提供存储支持,也可以选择mysql,broker。

mysql类型用来存储维表,由用户自己维护,方便修改。查询的时候,Doris可以自动实现mysql表和olap表的连接操作。使用mysql类型,需要提供以下properties信息

PROPERTIES (    
 "host" = "mysql_server_host",    
 "port" = "mysql_server_port",   
 "user" = "your_user_name",  
 "password" = "your_password",   
 "database" = "database_name",   
 "table" = "table_name"   
 )

“table”条目中的“table_name”是mysql中的真实表名。而CREATE TABLE语句中的table_name是该mysql表在Doris中的名字,二者可以不同。

broker类型表示表的访问需要通过指定的broker, 需要在 properties 提供以下信息

PROPERTIES (
 "broker_name" = "broker_name",
 "paths" = "file_path1[,file_path2]",
 "column_separator" = "value_separator",
 "line_delimiter" = "value_delimiter"
)

另外还可以提供Broker需要的Property信息,通过BROKER PROPERTIES来传递,例如HDFS需要传入

BROKER PROPERTIES(
 "username" = "name",
 "password" = "password"
)

这个根据不同的Broker类型,需要传入的内容也不相同

其中"paths" 中如果有多个文件,用逗号[,]分割。如果文件名中包含逗号,那么使用 %2c 来替代。如果文件名中包含 %,使用 %25 代替。现在文件内容格式支持CSV,支持GZ,BZ2,LZ4,LZO(LZOP) 压缩格式。

key_desc

语法:

key_type(k1[,k2 ...])

说明:

数据按照指定的key列进行排序,且根据不同的key_type具有不同特性。

key_type支持一下类型:

  • AGGREGATE KEY:key列相同的记录,value列按照指定的聚合类型进行聚合,适合报表、多维分析等业务场景。
  • UNIQUE KEY:key列相同的记录,value列按导入顺序进行覆盖,适合按key列进行增删改查的点查询业务。
  • DUPLICATE KEY:key列相同的记录,同时存在于Doris中,适合存储明细数据或者数据无聚合特性的业务场景。

partition_desc

语法:

 PARTITION BY RANGE (k1)   
 (    
 PARTITION partition_name VALUES LESS THAN MAXVALUE|("value1") [("key"="value")],    
 PARTITION partition_name VALUES LESS THAN MAXVALUE|("value2") [("key"="value")],    
 ...   
 )

Partition使用指定的key列和指定的数据范围对数据进行分区,每个分区在物理上对应不同的数据块,便于快速过滤和按分区删除等操作。目前只支持按Range分区,只能有一个分区列,分区列必须是key列。注意,最后一个PARTITION从句之后没有逗号。

说明:

  • 分区名称仅支持字母开头,并且只能由字母、数字和下划线组成
  • 目前只支持以下类型的列作为分区列,且只能指定一个分区列TINYINT, SAMLLINT, INT, BIGINT, LARGEINT, DATE, DATETIME
  • 分区为左闭右开区间,首个分区的左边界做为最小值
  • 如果指定了分区,无法确定分区范围的导入数据会被过滤掉
  • 每个分区后面的key-value键值对可以设置该分区的一些属性,目前支持如下属性:

    • storage_medium:用于指定该分区的初始存储介质,可选择SSD或HDD。默认为HDD。单节点SSD容量为50G,可以根据性能需求和数据量选择存储介质。
    • storage_cooldown_time:当设置存储介质为SSD时,指定该分区在SSD上的存储到期时间。默认存放7天。格式为:"yyyy-MM-dd HH:mm:ss"。到期后数据会自动迁移到HDD上。
    • replication_num:指定分区的副本数。默认为3

distribution_desc

distribution用来指定如何分桶,可以选择Random分桶和Hash分桶两种分桶方式。

Random分桶语法:

 DISTRIBUTED BY RANDOM [BUCKETS num]

Hash分桶语法:

 DISTRIBUTED BY HASH (k1[,k2 ...]) [BUCKETS num]

说明:

  • Random使用所有key列进行哈希分桶,默认分区数为10。Hash使用指定的key列进行分桶,默认分区数为10。如果ENGINE类型为olap,必须指定分桶方式;如果是mysql则无须指定。
  • 不建议使用Random分桶,建议使用Hash分桶。

properties

如果ENGINE类型为olap,则可以在properties中指定行存或列存

如果ENGINE类型为olap,且没有指定partition信息,可以在properties设置存储介质、存储到期时间和副本数等属性。如果指定了partition信息,需要为每个partition分别指定属性值,参考partition_desc

 PROPERTIES (    
 "storage_medium" = "[SSD|HDD]",    
 ["storage_cooldown_time" = "yyyy-MM-dd HH:mm:ss"],    
 ["replication_num" = "3"]    
 )

如果ENGINE类型为 olap, 并且 storage_type 为 column, 可以指定某列使用 bloom filter 索引。bloom filter 索引仅适用于查询条件为 in 和 equal 的情况,该列的值越分散效果越好。目前只支持以下情况的列:除了 TINYINT FLOAT DOUBLE 类型以外的 key 列及聚合方法为 REPLACE 的 value 列

 PROPERTIES (
 "bloom_filter_columns"="k1,k2,k3"
 )

关于建表的补充说明

  • Partition和Distribution的说明:

    • Doris支持复合分区,第一级称为Partition,对应建表语句中的partition_desc从句;第二级称为Distribution,对应建表语句中的distribution_desc从句。Partition是可选的,如果建表时没有指定Partition,系统会自动创建唯一的一个Partition。Distribution必须显式指定。在以下场景中推荐创建Partition:
    • 历史数据删除需求:如有删除历史数据的需求(比如仅保留最近N天的数据)。使用复合分区,可以通过删除历史分区来达到目的。
    • 解决数据倾斜问题:每个分区可以单独指定分桶数量。如按天分区,当每天的数据量差异很大时,可以通过指定分区的分桶数,合理划分不同分区的数据。
    • 如有按时间维度进行数据划分、导入、查询、删除、历史数据回溯等业务需求,推荐使用复合分区功能。
  • 合理的表模式:

Doris中使用类似前缀索引的结构来提高查询性能。数据在Doris内部是按照key列排序的,并且组织为一个个Data Block。每个Data Block的第一行的前几列会被用作这个Data Block的索引,在数据导入时创建。该索引可以帮助Doris快速过滤一些Data Block。考虑到索引大小等因素,Doris最多使用一行的前36个字节作为索引,遇到VARCHAR类型则会中断,并且VARCHAR类型最多只使用字符串的前20个字节。下面举例说明。

表1的schema:

image3-17.png

前三列的长度和为(4+8+24=)36,正好36字节,所以前三列被用作前缀索引。

表2的schema:

image3-18.png

前两列的长度为(4+8=)12,没有达到36,但是第三列为varchar,所以前三列被用作索引,其中k3只去前20字节。

表3的schema:

image3-19.png

该表第一列是varchar类型,所以只有k3列的前20字节作为索引。

表4的schema:

image3-20.png

前四列的长度和为(8+8+8+8=)32,如果加上第五列(8个字节),就会超过36字节。所以只有前四列被用作索引。

如果对于表2和表3执行同样的语句:

SELECT * from tbl WHERE k1 = 12345;

表2的性能会明显优于表3,因为在表2中可以用到k1索引,而表3只有k3作为索引,该查询会进行扫全表的操作。因此,在建表时,应该尽量将频繁使用,选择度高的列放在前面,尽量不要将varchar类型放在前几列,尽量使用整型作为索引列。

举例:

1.创建一个olap表,使用Random分桶,使用列存,相同key的记录进行聚合

CREATE TABLE example_db.table_random    
(    
k1 TINYINT,    
k2 DECIMAL(10, 2) DEFAULT "10.5",    
v1 CHAR(10) REPLACE,   
v2 INT SUM  
)   
ENGINE=olap
AGGREGATE KEY(k1, k2)   
DISTRIBUTED BY RANDOM BUCKETS 32    
PROPERTIES ("storage_type"="column");

2.创建一个olap表,使用Hash分桶,使用行存,相同key的记录进行覆盖。设置初始存储介质和存放到期时间。

 CREATE TABLE example_db.table_hash    
 (    
 k1 BIGINT,    
 k2 LARGEINT,    
 v1 VARCHAR(2048),   
 v2 SMALLINT DEFAULT "10"   
 )   
 ENGINE=olap
 UNIQUE KEY(k1, k2)   
 DISTRIBUTED BY HASH (k1, k2) BUCKETS 32   
 PROPERTIES(   
 "storage_type"="row",    
 "storage_medium" = "SSD",    
 "storage_cooldown_time" = "2015-06-04 00:00:00"    
 );

3.创建一个olap表,使用Key Range分区,使用Hash分桶。默认使用列存。相同key的记录同时存在。设置初始存储介质和存放到期时间。

 CREATE TABLE example_db.table_range    
 (    
 k1 DATE,    
 k2 INT,    
 k3 SMALLINT,   
 v1 VARCHAR(2048),   
 v2 DATETIME DEFAULT "2014-02-04 15:36:00"   
 )    
 ENGINE=olap
 DUPLICATE KEY(k1, k2, k3)    
 PARTITION BY RANGE (k1)   
 (    
 PARTITION p1 VALUES LESS THAN ("2014-01-01")   
 ("storage_medium" = "SSD", "storage_cooldown_time" = "2015-06-04 00:00:00"),    
 PARTITION p2 VALUES LESS THAN ("2014-06-01")   
 ("storage_medium" = "SSD", "storage_cooldown_time" = "2015-06-04 00:00:00"),    
 PARTITION p3 VALUES LESS THAN ("2014-12-01")    
 )    
 DISTRIBUTED BY HASH(k2) BUCKETS 32;

说明:

这个语句会将数据划分成如下3个分区:

 ( { MIN }, {"2014-01-01"} )    
 [ {"2014-01-01"}, {"2014-06-01"} )   
 [ {"2014-06-01"}, {"2014-12-01"} )

不在这些分区范围内的数据将视为非法数据被过滤

4.创建一个 mysql 表

 CREATE TABLE example_db.table_mysql   
 (    
 k1 DATE,    
 k2 INT,   
 k3 SMALLINT,    
 k4 VARCHAR(2048),    
 k5 DATETIME    
 )    
 ENGINE=mysql    
 PROPERTIES    
 (   
 "host" = "127.0.0.1",    
 "port" = "8239",    
 "user" = "mysql_user",    
 "password" = "mysql_passwd",    
 "database" = "mysql_db_test",    
 "table" = "mysql_table_test"    
 )

5.创建一个数据文件存储在HDFS上的 broker 外部表, 数据使用 "|" 分割,"\n" 换行

CREATE EXTERNAL TABLE example_db.table_broker 
(
k1 DATE,
k2 INT,
k3 SMALLINT,
k4 VARCHAR(2048),
k5 DATETIME
)
ENGINE=broker
PROPERTIES (
    "broker_name" = "hdfs",
    "path" = "hdfs://hdfs_host:hdfs_port/data1,hdfs://hdfs_host:hdfs_port/data2,hdfs://hdfs_host:hdfs_port/data3%2c4",
    "column_separator" = "|",
    "line_delimiter" = "\n"
)
BROKER PROPERTIES (
    "username" = "hdfs_user",
    "password" = "hdfs_password"
)

6.创建一个含有HLL列的表

CREATE TABLE example_db.example_table
(
k1 TINYINT,
k2 DECIMAL(10, 2) DEFAULT "10.5",
v1 HLL HLL_UNION,
v2 HLL HLL_UNION
)
ENGINE=olap
AGGREGATE KEY(k1, k2)
DISTRIBUTED BY RANDOM BUCKETS 32
PROPERTIES ("storage_type"="column");

Drop Database

该语句用于删除数据库(database)

语法:

DROP DATABASE [IF EXISTS] db_name;

举例:

删除数据库 db_test

 DROP DATABASE db_test;

Drop Table

该语句用于删除表(table)

语法:

 DROP TABLE [IF EXISTS] [db_name.]table_name;

举例:

1.删除一个 table

 DROP TABLE my_table;

2.如果存在,删除指定 database 的 table

 DROP TABLE IF EXISTS example_db.my_table;

Alter Database

该语句用于设置指定数据库的配额。(仅管理员使用)

语法:

 ALTER DATABASE db_name SET DATA QUOTA quota;

举例:

设置指定数据库数据量配额为1GB

 ALTER DATABASE example_db SET DATA QUOTA 1073741824;

Alter Table

该语句用于对已有的table进行修改。该语句分为三种操作类型:partition、rollup和schema change。Partition是上文提到的复合分区中的第一级分区;rollup是物化索引相关的操作;schema change用来修改表结构。这三种操作不能同时出现在一条ALTER TABLE语句中。其中schema change和rollup是异步操作,任务提交成功则返回,之后可以使用SHOW ALTER命令查看进度。Partition是同步操作,命令返回表示执行完毕。

语法:

 ALTER TABLE [database.]table alter_clause1[, alter_clause2, ...];

Alter_clause分为partition、rollup、schema change和rename四种。

partition支持的操作

增加分区

语法:

 ADD PARTITION [IF NOT EXISTS] partition_name VALUES LESS THAN [MAXVALUE|("value1")] ["key"="value"] [DISTRIBUTED BY RANDOM [BUCKETS num] | DISTRIBUTED BY HASH (k1[,k2 ...]) [BUCKETS num]]

注意:

  • 分区为左闭右开区间,用户指定右边界,系统自动确定左边界
  • 如果没有指定分桶方式,则自动使用建表使用的分桶方式
  • 如果已经指定分桶方式,则只能修改分桶数,不可修改分桶方式或分桶列
  • ["key"="value"] 部分可以设置分区的一些属性,具体说明见CREATE TABLE

删除分区

语法:

 DROP PARTITION [IF EXISTS] partition_name

注意:

  • 使用分区方式的表至少要保留一个分区
  • 执行 DROP PARTITION 一段时间内,可以通过 RECOVER 语句恢复被删除的 partition。详见 RECOVER 语句

修改分区属性

语法:

 MODIFY PARTITION partition_name SET ("key" = "value", ...)

说明:

  • 当前支持修改分区的 storage_medium、storage_cooldown_time 和replication_num 三个属性。
  • 建表时没有指定partition时,partition_name同表名。

rollup支持的操作

rollup index类似于物化视图。建表完成之后,这张表中没有rollup index,只有一个base index,这个index的name和表名相同。用户可以为一张表建立一个或多个rollup index,每个rollup index包含base index中key和value列的一个子集,Doris会为这个子集生成独立的数据,用来提升查询性能。如果一个查询涉及到的列全部包含在一个rollup index中,Doris会选择扫瞄这个rollup index而不是全部的数据。用户可以根据自己应用的特点选择创建rollup index,rollup支持的操作:

创建 rollup index

语法:

 ADD ROLLUP rollup_name (column_name1, column_name2, ...) [FROM from_index_name] [PROPERTIES ("key"="value", ...)]

注意:

  • 如果没有指定from_index_name,则默认从base index创建
  • rollup表中的列必须是from_index中已有的列
  • 在properties中,可以指定存储格式。具体请参阅 CREATE TABLE

删除 rollup index

语法:

 DROP ROLLUP rollup_name   
 [PROPERTIES ("key"="value", ...)]

注意:

  • 不能删除 base index
  • 执行 DROP ROLLUP 一段时间内,可以通过 RECOVER 语句恢复被删除的 rollup index。详见 RECOVER 语句

schema change

Schema change操作用来修改表结构,包括添加列、删除列、修改列类型以及调整列顺序等。可以修改base index和rollup index的结构。

Schema change支持的操作:

向指定index的指定位置添加一列

语法:

 ADD COLUMN column_name column_type [KEY | agg_type] [DEFAULT "default_value"]    
 [AFTER column_name|FIRST]    
 [TO index_name]    
 [PROPERTIES ("key"="value", ...)]

注意:

  • 聚合模型如果增加 value 列,需要指定agg_type
  • 非聚合模型如果增加key列,需要指定KEY关键字
  • 不能在rollup index中增加base index中已经存在的列。如有需要,可以重新创建一个 rollup index

向指定index添加多列

语法:

 ADD COLUMN (column_name1 column_type [KEY | agg_type] DEFAULT "default_value", ...)   
 [TO index_name]    
 [PROPERTIES ("key"="value", ...)]

注意:

  • 聚合模型如果增加 value 列,需要指定agg_type
  • 非聚合模型如果增加key列,需要指定KEY关键字
  • 不能在rollup index中增加base index中已经存在的列,如有需要,可以重新创建一个 rollup index。

从指定 index 中删除一列

语法:

 DROP COLUMN column_name [FROM index_name]

注意:

  • 不能删除分区列
  • 如果是从base index中删除列,那么rollup index中如果包含该列,也会被删除

修改指定index的列类型以及列位置

语法:

 MODIFY COLUMN column_name column_type [KEY | agg_type] [DEFAULT "default_value"]    
 [AFTER column_name|FIRST]    
 [FROM index_name]    
 [PROPERTIES ("key"="value", ...)]

注意:

  • 聚合类型如果修改value列,需要指定agg_type
  • 非聚合类型如果修改key列,需要指定KEY关键字
  • 只能修改列的类型,列的其他属性维持原样(即其他属性需在语句中按照原属性显式的写出,参考schema change举例5)
  • 分区列不能做任何修改
  • 目前支持以下类型的转换(精度损失由用户保证)。TINYINT, SMALLINT, INT, BIGINT转换成TINYINT, SMALLINT, INT, BIGINT, DOUBLE。LARGEINT转换成DOUBLE 。VARCHAR支持修改最大长度
  • 不支持从NULL转为NOT NULL

对指定index的列进行重新排序

语法:

 ORDER BY (column_name1, column_name2, ...)    
 [FROM index_name]    
 [PROPERTIES ("key"="value", ...)]

注意:

  • index中的所有列都要写出来
  • value列在key列之后

rename

Rename操作用来修改表名、rollup index名称和partition名称

Rename支持的操作:

修改表名

语法:

RENAME new_table_name

修改rollup index名称

语法:

RENAME ROLLUP old_rollup_name new_rollup_name

修改partition名称

语法:

RENAME PARTITION old_partition_name new_partition_name

举例:

1.增加分区, 现有分区 [MIN, 2013-01-01),增加分区[2013-01-01, 2014-01-01),使用默认分桶方式

 ALTER TABLE example_db.my_table   
 ADD PARTITION p1 VALUES LESS THAN ("2014-01-01");

2.增加分区,使用新的分桶方式

 ALTER TABLE example_db.my_table   
 ADD PARTITION p1 VALUES LESS THAN ("2015-01-01")    
 DISTRIBUTED BY RANDOM BUCKETS 20;

3.删除分区

 ALTER TABLE example_db.my_table   
 DROP PARTITION p1;

4.创建index: example_rollup_index,基于 base index(k1,k2,k3,v1,v2),列式存储。

 ALTER TABLE example_db.my_table    
 ADD ROLLUP example_rollup_index(k1, k3, v1, v2)    
 PROPERTIES("storage_type"="column");

5.创建index: example_rollup_index2,基于example_rollup_index(k1,k3,v1,v2)

 ALTER TABLE example_db.my_table    
 ADD ROLLUP example_rollup_index2 (k1, v1)    
 FROM example_rollup_index;

6.删除index: example_rollup_index2

 ALTER TABLE example_db.my_table    
 DROP ROLLUP example_rollup_index2;

7.向example_rollup_index的col1后添加一个key列new_col(非聚合模型)

 ALTER TABLE example_db.my_table   
 ADD COLUMN new_col INT KEY DEFAULT "0" AFTER col1    
 TO example_rollup_index;

8.向example_rollup_index的col1后添加一个value列new_col(非聚合模型)

 ALTER TABLE example_db.my_table   
 ADD COLUMN new_col INT DEFAULT "0" AFTER col1    
 TO example_rollup_index;

9.向example_rollup_index的col1后添加一个key列new_col(聚合模型)

 ALTER TABLE example_db.my_table   
 ADD COLUMN new_col INT DEFAULT "0" AFTER col1    
 TO example_rollup_index;

10.向example_rollup_index的col1后添加一个value列new_col SUM聚合类型(聚合模型)

 ALTER TABLE example_db.my_table   
 ADD COLUMN new_col INT SUM DEFAULT "0" AFTER col1    
 TO example_rollup_index;

11.向 example_rollup_index 添加多列(聚合模型)

 ALTER TABLE example_db.my_table    
 ADD COLUMN (col1 INT DEFAULT "1", col2 FLOAT SUM DEFAULT "2.3")    
 TO example_rollup_index;

12.从example_rollup_index删除一列

 ALTER TABLE example_db.my_table    
 DROP COLUMN col2    
 FROM example_rollup_index;

13.修改base index的col1列的类型为BIGINT,并移动到col2列后面

 ALTER TABLE example_db.my_table    
 MODIFY COLUMN col1 BIGINT DEFAULT "1" AFTER col2;

14.修改base index的val1列最大长度。原val1为(val1 VARCHAR(32) REPLACE DEFAULT "abc")

 ALTER TABLE example_db.my_table    
 MODIFY COLUMN val1 VARCHAR(64) REPLACE DEFAULT "abc";

15.重新排序example_rollup_index中的列(设原列顺序为:k1,k2,k3,v1,v2)

 ALTER TABLE example_db.my_table    
 ORDER BY (k3,k1,k2,v2,v1)    
 FROM example_rollup_index;

16.同时执行两种操作

 ALTER TABLE example_db.my_table    
 ADD COLUMN v2 INT MAX DEFAULT "0" AFTER k2 TO example_rollup_index,   
 ORDER BY (k3,k1,k2,v2,v1) FROM example_rollup_index;

17.修改表的 bloom filter 列

 ALTER TABLE example_db.my_table
 PROPERTIES ("bloom_filter_columns"="k1,k2,k3");

18.将名为 table1 的表修改为 table2

 ALTER TABLE table1 RENAME table2;

19.将表 example_table 中名为 rollup1 的 rollup index 修改为 rollup2

 ALTER TABLE example_table RENAME ROLLUP rollup1 rollup2;

20.将表 example_table 中名为 p1 的 partition 修改为 p2

 ALTER TABLE example_table RENAME PARTITION p1 p2;

Cancel Alter

该语句用于撤销一个alter操作

撤销alter table column (即schema change)语法:

 CANCEL ALTER TABLE COLUMN FROM db_name.table_name

撤销alter table rollup操作

 CANCEL ALTER TABLE ROLLUP FROM db_name.table_name

举例:

1.撤销针对 my_table 的 ALTER COLUMN 操作。

 CANCEL ALTER TABLE COLUMN    
 FROM example_db.my_table;

2.撤销 my_table 下的 ADD ROLLUP 操作。

 CANCEL ALTER TABLE ROLLUP    
 FROM example_db.my_table;

DML语句

Load

该语句用于向指定的table导入数据。该操作会同时更新和此table相关的base index和rollup index的数据。这是一个异步操作,任务提交成功则返回。执行后可使用SHOW LOAD命令查看进度。

NULL导入的时候用\N来表示。如果需要将其他字符串转化为NULL,可以使用replace_value进行转化。

语法:

 LOAD LABEL load_label    
 (    
 data_desc1[, data_desc2, ...]    
 )
 broker    
 [opt_properties];

load_label

load_label是当前导入批次的标签,由用户指定,需要保证在一个database是唯一的。也就是说,之前在某个database成功导入的label不能在这个database中再使用。该label用来唯一确定database中的一次导入,便于管理和查询。

语法:

 [database_name.]your_label

data_desc

用于具体描述一批导入数据。

语法:

 DATA INFILE    
 (    
 "file_path1 [, file_path2, ...]    
 )   
 [NEGATIVE]   
 INTO TABLE table_name   
 [PARTITION (p1, p2)]   
 [COLUMNS TERMINATED BY "column_separator"]    
 [(column_list)]   
 [SET (k1 = func(k2))]

说明:

  • file_path,broker中的文件路径,可以指定到一个文件,也可以用/*通配符指定某个目录下的所有文件。
  • NEGATIVE:如果指定此参数,则相当于导入一批“负”数据。用于抵消之前导入的同一批数据。该参数仅适用于存在value列,并且value列的聚合类型为SUM的情况。不支持Broker方式导入
  • PARTITION:如果指定此参数,则只会导入指定的分区,导入分区以外的数据会被过滤掉。如果不指定,默认导入table的所有分区。
  • column_separator:用于指定导入文件中的列分隔符。默认为\t。如果是不可见字符,则需要加\\x作为前缀,使用十六进制来表示分隔符。如hive文件的分隔符\x01,指定为"\\x01"
  • column_list:用于指定导入文件中的列和table中的列的对应关系。当需要跳过导入文件中的某一列时,将该列指定为table中不存在的列名即可,语法:

    (col_name1, col_name2, ...)

  • SET: 如果指定此参数,可以将源文件某一列按照函数进行转化,然后将转化后的结果导入到table中。目前支持的函数有:

    • strftime(fmt, column) 日期转换函数

      • fmt: 日期格式,形如%Y%m%d%H%M%S (年月日时分秒)
      • column: column_list中的列,即输入文件中的列。存储内容应为数字型的时间戳。如果没有column_list,则按照doris表的列顺序默认输入文件的列。
    • time_format(output_fmt, input_fmt, column) 日期格式转化

      • output_fmt: 转化后的日期格式,形如%Y%m%d%H%M%S (年月日时分秒)
      • input_fmt: 转化前column列的日期格式,形如%Y%m%d%H%M%S (年月日时分秒)
      • column: column_list中的列,即输入文件中的列。存储内容应为input_fmt格式的日期字符串。如果没有column_list,则按照doris表的列顺序默认输入文件的列。
    • alignment_timestamp(precision, column) 将时间戳对齐到指定精度

      • precision: year|month|day|hour
      • column: column_list中的列,即输入文件中的列。存储内容应为数字型的时间戳。 如果没有column_list,则按照doris表的列顺序默认输入文件的列。
      • 注意:对齐精度为year、month的时候,只支持20050101~20191231范围内的时间戳。
    • default_value(value) 设置某一列导入的默认值,不指定则使用建表时列的默认值
    • md5sum(column1, column2, ...) 将指定的导入列的值求md5sum,返回32位16进制字符串
    • replace_value(old_value[, new_value]) 导入文件中指定的old_value替换为new_value。new_value如不指定则使用建表时列的默认值
    • hll_hash(column) 用于将表或数据里面的某一列转化成HLL列的数据结构

broker

用于指定导入使用的Broker

语法:

 WITH BROKER broker_name ("key"="value"[,...])

这里需要指定具体的Broker name, 以及所需的Broker属性

opt_properties

用于指定一些特殊参数。

语法:

 [PROPERTIES ("key"="value", ...)]

可以指定如下参数:

  • timeout:指定导入操作的超时时间。默认不超时。单位秒
  • max_filter_ratio:最大容忍可过滤(数据不规范等原因)的数据比例。默认零容忍。
  • load_delete_flag:指定该导入是否通过导入key列的方式删除数据,仅适用于UNIQUE KEY,导入时可不指定value列。默认为false (不支持Broker方式导入)
  • exe_mem_limit:在Broker Load方式时生效,指定导入执行时,后端可使用的最大内存。

举例:

1.导入一批数据,指定个别参数

 LOAD LABEL example_db.label1    
 (    
 DATA INFILE("hdfs://hdfs_host:hdfs_port/user/doris/data/input/file")   
 INTO TABLE my_table   
 )
 WITH BROKER hdfs ("username"="hdfs_user", "password"="hdfs_password")   
 PROPERTIES    
 (   
 "timeout"="3600",    
 "max_filter_ratio"="0.1",    
 );

2.导入一批数据,包含多个文件。导入不同的 table,指定分隔符,指定列对应关系

 LOAD LABEL example_db.label2
 (   
 DATA INFILE("hdfs://hdfs_host:hdfs_port/user/doris/data/input/file1")    
 INTO TABLE my_table_1    
 COLUMNS TERMINATED BY ","    
 (k1, k3, k2, v1, v2),    
 DATA INFILE("hdfs://hdfs_host:hdfs_port/user/doris/data/input/file2")    
 INTO TABLE my_table_2    
 COLUMNS TERMINATED BY "\t"   
 (k1, k2, k3, v2, v1)    
 )    
 WITH BROKER hdfs ("username"="hdfs_user", "password"="hdfs_password");

3.导入一批数据,指定hive的默认分隔符\x01,并使用通配符*指定目录下的所有文件

 LOAD LABEL example_db.label3   
 (   
 DATA INFILE("hdfs://hdfs_host:hdfs_port/user/doris/data/input/*")    
 NEGATIVE    
 INTO TABLE my_table    
 COLUMNS TERMINATED BY "\\x01"    
 )
 WITH BROKER hdfs ("username"="hdfs_user", "password"="hdfs_password");

4.导入一批“负”数据

 LOAD LABEL example_db.label4   
 (    
 DATA INFILE("hdfs://hdfs_host:hdfs_port/user/doris/data/input/old_file")    
 NEGATIVE    
 INTO TABLE my_table    
 COLUMNS TERMINATED BY "\t"   
 )
 WITH BROKER hdfs ("username"="hdfs_user", "password"="hdfs_password");

5.导入一批数据,指定分区

 LOAD LABEL example_db.label5    
 (   
 DATA INFILE("hdfs://hdfs_host:hdfs_port/user/doris/data/input/file")    
 INTO TABLE my_table    
 PARTITION (p1, p2)    
 COLUMNS TERMINATED BY ","    
 (k1, k3, k2, v1, v2)   
 )
 WITH BROKER hdfs ("username"="hdfs_user", "password"="hdfs_password");

6.导入一批数据,指定分区, 并对导入文件的列做一些转化,如下:

  • k1将tmp_k1时间戳列转化为datetime类型的数据
  • k2将tmp_k2 date类型的数据转化为datetime的数据
  • k3将tmp_k3时间戳列转化为天级别时间戳
  • k4指定导入默认值为1
  • k5将tmp_k1、tmp_k2、tmp_k3列计算md5串

导入语句为:

 LOAD LABEL example_db.label6
 (
 DATA INFILE("hdfs://hdfs_host:hdfs_port/user/doris/data/input/file")
 INTO TABLE my_table
 PARTITION (p1, p2)
 COLUMNS TERMINATED BY ","
 (tmp_k1, tmp_k2, tmp_k3, v1, v2)
 SET (
   k1 = strftime("%Y-%m-%d %H:%M:%S", tmp_k1)),     
   k2 = time_format("%Y-%m-%d %H:%M:%S", "%Y-%m-%d", tmp_k2)),      
   k3 = alignment_timestamp("day", tmp_k3),     
   k4 = default_value("1"),     
   k5 = md5sum(tmp_k1, tmp_k2, tmp_k3)  
 )
 )
 WITH BROKER hdfs ("username"="hdfs_user", "password"="hdfs_password"); 

7.导入数据到含有HLL列的表,可以是表中的列或者数据里面的列

 LOAD LABEL example_db.label7
 (
 DATA INFILE("hdfs://hdfs_host:hdfs_port/user/doris/data/input/file")
 INTO TABLE my_table
 PARTITION (p1, p2)
 COLUMNS TERMINATED BY ","
 SET (
   v1 = hll_hash(k1),
   v2 = hll_hash(k2)
 )
 )
 WITH BROKER hdfs ("username"="hdfs_user", "password"="hdfs_password"); 

 LOAD LABEL example_db.label8
 (
 DATA INFILE("hdfs://hdfs_host:hdfs_port/user/doris/data/input/file")
 INTO TABLE `my_table`
 PARTITION (p1, p2)
 COLUMNS TERMINATED BY ","
 (k1, k2, tmp_k3, tmp_k4, v1, v2)
 SET (
   v1 = hll_hash(tmp_k3),
   v2 = hll_hash(tmp_k4)
 )
 )
 WITH BROKER hdfs ("username"="hdfs_user", "password"="hdfs_password");

小批量导入

小批量导入是Doris新提供的一种导入方式,这种导入方式可以使用户不依赖 Hadoop,从而完成导入。此种导入方式提交任务并不是通过MySQL客户端,而是通过http协议来完成的。用户通过http协议将导入描述和数据一同发送给Doris,Doris在接收任务成功后,会立即返回给用户成功信息,但是此时,数据并未真正导入。用户需要通过 'SHOW LOAD' 命令来查看具体的导入结果。

语法:

 curl --location-trusted -u user:passwd -T data.file http://fe.host:port/api/{db}/{table}/_load?label=xxx

参数说明:

  • user:用户如果是在default_cluster中的,user即为user_name。否则为user_name@cluster_name。
  • label:用于指定这一批次导入的label,用于后期进行作业状态查询等。 这个参数是必须传入的。
  • columns: 用于描述导入文件中对应的列名字。如果不传入,那么认为文件中的列顺序与建表的顺序一致,指定的方式为逗号分隔,例如:columns=k1,k2,k3,k4
  • column_separator: 用于指定列与列之间的分隔符,默认的为'\t'。需要注意的是,这里应使用url编码,例如需要指定'\t'为分隔符,那么应该传入'column_separator=%09';需要指定'\x01'为分隔符,那么应该传入'column_separator=%01'
  • max_filter_ratio: 用于指定允许过滤不规范数据的最大比例,默认是0,不允许过滤。自定义指定应该如下:'max_filter_ratio=0.2',含义是允许20%的错误率。
  • hll:用于指定数据里面和表里面的HLL列的对应关系,表中的列和数据里面指定的列(如果不指定columns,则数据列里面的列也可以是表里面的其它非HLL列)通过","分割,指定多个hll列使用“:”分割,例如: 'hll1,cuid:hll2,device'

举例:

1.将本地文件'testData'中的数据导入到数据库'testDb'中'testTbl'的表(用户是defalut_cluster中的)

 curl --location-trusted -u root:root -T testData http://fe.host:port/api/testDb/testTbl/_load?label=123

2.将本地文件'testData'中的数据导入到数据库'testDb'中'testTbl'的表(用户是test_cluster中的)

 curl --location-trusted -u root@test_cluster:root -T testData http://fe.host:port/api/testDb/testTbl/_load?label=123

3.将本地文件'testData'中的数据导入到数据库'testDb'中'testTbl'的表, 允许20%的错误率(用户是defalut_cluster中的)

 curl --location-trusted -u root -T testData http://fe.host:port/api/testDb/testTbl/_load?label=123\$amp;max_filter_ratio=0.2

4.将本地文件'testData'中的数据导入到数据库'testDb'中'testTbl'的表, 允许20%的错误率,并且指定文件的列名(用户是defalut_cluster中的)

 curl --location-trusted -u root -T testData http://fe.host:port/api/testDb/testTbl/_load?label=123\$amp;max_filter_ratio=0.2\$amp;columns=k1,k2,k3

5.使用streaming方式导入(用户是defalut_cluster中的)

 seq 1 10 | awk '{OFS="\\t"}{print $1, $1 * 10}' | curl --location-trusted -u root -T testData http://fe.host:port/api/testDb/testTbl/_load?label=123

6.导入含有HLL列的表,可以是表中的列或者数据中的列用于生成HLL列(用户是defalut_cluster中的)

 curl --location-trusted -u root -T testData http://host:port/api/testDb/testTbl/_load?label=123\&max_filter_ratio=0.2\&hll=hll_column1,k1:hll_column2,k2
        
 curl --location-trusted -u root -T testData http://host:port/api/testDb/testTbl/_load?label=123\&max_filter_ratio=0.2\&hll=hll_column1,tmp_k4:hll_column2,tmp_k5\&columns=k1,k2,k3,tmp_k4,tmp_k5

Cancel Load

Cancel load用于撤销指定load label的导入作业。这是一个异步操作,任务提交成功就返回。提交后可以使用show load命令查看进度。

语法:

 CANCEL LOAD [FROM db_name] WHERE LABEL = "load_label";

举例:

撤销数据库 example_db 上, label 为 example_db_test_load_label 的导入作业

 CANCEL LOAD FROM example_db WHERE LABEL = "example_db_test_load_label";

Export

该语句用于将指定表的数据导出到指定位置。这是一个异步操作,任务提交成功则返回。执行后可使用 SHOW EXPORT 命令查看进度。

语法:

 EXPORT TABLE table_name
 [PARTITION (p1[,p2])]
 TO export_path
 [opt_properties]
 broker;

table_name

当前要导出的表的表名,目前支持engine为olap和mysql的表的导出。

partition

可以只导出指定表的某些指定分区

export_path

导出的路径,需为目录。目前不能导出到本地,需要导出到broker。

opt_properties

用于指定一些特殊参数。

语法:

 [PROPERTIES ("key"="value", ...)]

可以指定如下参数:

  • column_separator:指定导出的列分隔符,默认为\t。
  • line_delimiter:指定导出的行分隔符,默认为\n。

broker

用于指定导出使用的broker

语法:

 WITH BROKER broker_name ("key"="value"[,...])

这里需要指定具体的broker name, 以及所需的broker属性

举例:

1.将testTbl表中的所有数据导出到hdfs上

 EXPORT TABLE testTbl TO "hdfs://hdfs_host:port/a/b/c" WITH BROKER "broker_name" ("username"="xxx", "password"="yyy");

2.将testTbl表中的分区p1,p2导出到hdfs上

 EXPORT TABLE testTbl PARTITION (p1,p2) TO "hdfs://hdfs_host:port/a/b/c" WITH BROKER "broker_name" ("username"="xxx", "password"="yyy");

3.将testTbl表中的所有数据导出到hdfs上,以","作为列分隔符

 EXPORT TABLE testTbl TO "hdfs://hdfs_host:port/a/b/c" PROPERTIES ("column_separator"=",") WITH BROKER "broker_name" ("username"="xxx", "password"="yyy");

Delete

该语句用于按条件删除指定table(base index) partition中的数据。该操作会同时删除和此相关的rollup index的数据。

语法:

 DELETE FROM table_name PARTITION partition_name WHERE   
 column_name1 op value[ AND column_name2 op value ...];

说明:

  • op的可选类型包括:=, <, >, <=, >=, !=
  • 只能指定key列上的条件。
  • 条件之间只能是“与”的关系。若希望达成“或”的关系,需要将条件分写在两个 DELETE语句中。
  • 如果没有创建partition,partition_name 同 table_name。

注意:

  • 该语句可能会降低执行后一段时间内的查询效率,影响程度取决于语句中指定的删除条件的数量,指定的条件越多,影响越大。

举例:

1.删除 my_table partition p1 中 k1 列值为 3 的数据行

 DELETE FROM my_table PARTITION p1 WHERE k1 = 3;

2.删除 my_table partition p1 中 k1 列值大于等于 3 且 k2 列值为 "abc" 的数据行

 DELETE FROM my_table PARTITION p1 WHERE k1 >= 3 AND k2 = "abc";

SELECT语句

Select语句由select,from,where,group by,having,order by,union等部分组成,Doris的查询语句基本符合SQL92标准,下面详细介绍支持的select用法。

连接(Join)

连接操作是合并2个或多个表的数据,然后返回其中某些表中的某些列的结果集。目前Doris支持inner join,outer join,semi join,anti join, cross join。在inner join条件里除了支持等值join,还支持不等值join,为了性能考虑,推荐使用等值join。其它join只支持等值join。

语法:

 SELECT select_list FROM
     table_or_subquery1 [INNER] JOIN table_or_subquery2 |
     table_or_subquery1 {LEFT [OUTER] | RIGHT [OUTER] | FULL [OUTER]} JOIN table_or_subquery2 |
     table_or_subquery1 {LEFT | RIGHT} SEMI JOIN table_or_subquery2 |
     table_or_subquery1 {LEFT | RIGHT} ANTI JOIN table_or_subquery2 |
         [ ON col1 = col2 [AND col3 = col4 ...] |
             USING (col1 [, col2 ...]) ]
     [other_join_clause ...]
     [ WHERE where_clauses ]

 SELECT select_list FROM
     table_or_subquery1, table_or_subquery2 [, table_or_subquery3 ...]
     [other_join_clause ...]
 WHERE
     col1 = col2 [AND col3 = col4 ...]

 SELECT select_list FROM
     table_or_subquery1 CROSS JOIN table_or_subquery2
     [other_join_clause ...]
 [ WHERE where_clauses ]

Self-Join

Doris支持self-joins,即自己和自己join。例如同一张表的不同列进行join。实际上没有特殊的语法标识self-join。self-join中join两边的条件都来自同一张表,我们需要给他们分配不同的别名。

举例:

 SELECT lhs.id, rhs.parent, lhs.c1, rhs.c2 FROM tree_data lhs, tree_data rhs WHERE lhs.id = rhs.parent;

笛卡尔积(Cross Join)

Cross join会产生大量的结果,须慎用cross join,即使需要使用cross join时也需要使用过滤条件并且确保返回结果数较少。

举例:

 SELECT * FROM t1, t2;
 SELECT * FROM t1 CROSS JOIN t2;

Inner join

inner join 是大家最熟知,最常用的join。返回的结果来自相近的2张表所请求的列,join 的条件为两个表的列包含有相同的值。如果两个表的某个列名相同,我们需要使用全名(table_name.column_name形式)或者给列名起别名。

举例:

 -- The following 3 forms are all equivalent.
 SELECT t1.id, c1, c2 FROM t1, t2 WHERE t1.id = t2.id;
 SELECT t1.id, c1, c2 FROM t1 JOIN t2 ON t1.id = t2.id;
 SELECT t1.id, c1, c2 FROM t1 INNER JOIN t2 ON t1.id = t2.id;

Outer join

outer join返回左表或者右表或者两者所有的行。如果在另一张表中没有匹配的数据,则将其设置为NULL。

举例:

 SELECT * FROM t1 LEFT OUTER JOIN t2 ON t1.id = t2.id;
 SELECT * FROM t1 RIGHT OUTER JOIN t2 ON t1.id = t2.id;
 SELECT * FROM t1 FULL OUTER JOIN t2 ON t1.id = t2.id;

等值和不等值join

通常情况下,用户使用等值join居多,等值join要求join条件的操作符是等号。不等值join 在join条件上可以使用!,,<, >等符号。不等值join会产生大量的结果,在计算过程中可能超过内存限额,因此需要谨慎使用。不等值join只支持inner join。

举例:

 SELECT t1.id, c1, c2 FROM t1 INNER JOIN t2 ON t1.id = t2.id;
 SELECT t1.id, c1, c2 FROM t1 INNER JOIN t2 ON t1.id > t2.id;

Semi join

left semi join只返回左表中能匹配右表数据的行,不管能匹配右表多少行数据,左表的该行最多只返回一次。right semi join原理相似,只是返回的数据是右表的。

举例:

 SELECT t1.c1, t1.c2, t1.c2 FROM t1 LEFT SEMI JOIN t2 ON t1.id = t2.id;

Anti join

left anti join只返回左表中不能匹配右表的行。right anti join反转了这个比较,只返回右表中不能匹配左表的行。

举例:

 SELECT t1.c1, t1.c2, t1.c2 FROM t1 LEFT ANTI JOIN t2 ON t1.id = t2.id;

Order by

order by通过比较1列或者多列的大小来对结果集进行排序。order by是比较耗时耗资源的操作,因为所有数据都需要发送到1个节点后才能排序,排序操作相比不排序操作需要更多的内存。如果需要返回前N个排序结果,需要使用LIMIT从句;为了限制内存的使用,如果用户没有指定LIMIT从句,则默认返回前65535个排序结果。

语法:

ORDER BY col [ASC | DESC]

默认的排序是ASC

举例:

mysql> select * from big_table order by tiny_column, short_column desc;

Group by

group by从句通常和聚合函数(例如COUNT(), SUM(), AVG(), MIN()和MAX())一起使用。group by指定的列不会参加聚合操作。group by从句可以加入having从句来过滤聚合函数产出的结果。

举例:

 mysql> select tiny_column, sum(short_column) from small_table group by tiny_column;
 +-------------+---------------------+
 | tiny_column | sum(`short_column`) |
 +-------------+---------------------+
 |           1 |                   2 |
 |           2 |                   1 |
 +-------------+---------------------+
 2 rows in set (0.07 sec)

Having

having从句不是过滤表中的行数据,而是过滤聚合函数产出的结果。通常来说having要和聚合函数(例如COUNT(), SUM(), AVG(), MIN(), MAX())以及group by从句一起使用。

举例:

 mysql> select tiny_column, sum(short_column) from small_table group by tiny_column having sum(short_column) = 1;
 +-------------+---------------------+
 | tiny_column | sum(`short_column`) |
 +-------------+---------------------+
 |           2 |                   1 |
 +-------------+---------------------+
 1 row in set (0.07 sec)

 mysql> select tiny_column, sum(short_column) from small_table group by tiny_column having tiny_column > 1;
 +-------------+---------------------+
 | tiny_column | sum(`short_column`) |
 +-------------+---------------------+
 |           2 |                   1 |
 +-------------+---------------------+
 1 row in set (0.07 sec)

Limit

Limit从句用于限制返回结果的最大行数。设置返回结果的最大行数可以帮助Doris优化内存的使用。该从句主要应用如下场景:

  • 返回top-N的查询结果。
  • 想简单看下表中包含的内容。
  • 如果表中数据足够大,或者where从句没有过滤太多的数据,需要使用

使用说明:

limit从句的值必须是数字型字面常量。

举例:

 mysql> select tiny_column from small_table limit 1;
 +-------------+
 | tiny_column |
 +-------------+
 |           1 |
 +-------------+
 1 row in set (0.02 sec)

 mysql> select tiny_column from small_table limit 10000;
 +-------------+
 | tiny_column |
 +-------------+
 |           1 |
 |           2 |
 +-------------+
 2 rows in set (0.01 sec)

Offset

offset从句使得结果集跳过前若干行结果后直接返回后续的结果。结果集默认起始行为第0行,因此offset 0和不带offset返回相同的结果。通常来说,offset从句需要与order by从句和limit从句一起使用才有效。

举例:

 mysql> select varchar_column from big_table order by varchar_column limit 3;
 +----------------+
 | varchar_column |
 +----------------+
 | beijing        |
 | chongqing      |
 | tianjin        |
 +----------------+
 3 rows in set (0.02 sec)

 mysql> select varchar_column from big_table order by varchar_column limit 1 offset 0;
 +----------------+
 | varchar_column |
 +----------------+
 | beijing        |
 +----------------+
 1 row in set (0.01 sec)

 mysql> select varchar_column from big_table order by varchar_column limit 1 offset 1;
 +----------------+
 | varchar_column |
 +----------------+
 | chongqing      |
 +----------------+
 1 row in set (0.01 sec)

 mysql> select varchar_column from big_table order by varchar_column limit 1 offset 2;
 +----------------+
 | varchar_column |
 +----------------+
 | tianjin        |
 +----------------+
 1 row in set (0.02 sec)

注意:

在没有order by的情况下使用offset语法是允许的,但是此时offset无意义,这种情况只取limit的值,忽略掉offset的值。因此在没有order by的情况下,offset超过结果集的最大行数依然是有结果的。建议用户使用offset时一定要带上order by。

Union

Union从句用于合并多个查询的结果集。

语法:

query_1 UNION [DISTINCT | ALL] query_2

使用说明:

只使用union关键词和使用union disitnct的效果是相同的。由于去重工作是比较耗费内存的,因此使用union all操作查询速度会快些,耗费内存会少些。如果用户想对返回结果集进行order by和limit操作,需要将union操作放在子查询中,然后select from subquery,最后把subgquery和order by放在子查询外面。

举例:

 mysql> (select tiny_column from small_table) union all (select tiny_column from small_table);
 +-------------+
 | tiny_column |
 +-------------+
 |           1 |
 |           2 |
 |           1 |
 |           2 |
 +-------------+
 4 rows in set (0.10 sec)

 mysql> (select tiny_column from small_table) union (select tiny_column from small_table);    
 +-------------+
 | tiny_column |
 +-------------+
 |           2 |
 |           1 |
 +-------------+
 2 rows in set (0.11 sec)

 mysql> select * from (select tiny_column from small_table union all\
     -> select tiny_column from small_table) as t1 \
     -> order by tiny_column limit 4;
 +-------------+
 | tiny_column |
 +-------------+
 |           1 |
 |           1 |
 |           2 |
 |           2 |
 +-------------+
 4 rows in set (0.11 sec)

Distinct

Distinct操作符对结果集进行去重。

举例:

 mysql> -- Returns the unique values from one column.
 mysql> select distinct tiny_column from big_table limit 2;
 mysql> -- Returns the unique combinations of values from multiple columns.
 mysql> select distinct tiny_column, int_column from big_table limit 2;

distinct可以和聚合函数(通常是count函数)一同使用,count(disitnct)用于计算出一个列或多个列上包含多少不同的组合。

 mysql> -- Counts the unique values from one column.
 mysql> select count(distinct tiny_column) from small_table;
 +-------------------------------+
 | count(DISTINCT `tiny_column`) |
 +-------------------------------+
 |                             2 |
 +-------------------------------+
 1 row in set (0.06 sec)
 mysql> -- Counts the unique combinations of values from multiple columns.
 mysql> select count(distinct tiny_column, int_column) from big_table limit 2;

Doris支持多个聚合函数同时使用distinct

 mysql> -- Count the unique value from multiple aggregation function separately.
 mysql> select count(distinct tiny_column, int_column), count(distinct varchar_column) from big_table;

子查询

子查询按相关性分为不相关子查询和相关子查询。

不相关子查询

不相关子查询支持[NOT] IN和EXISTS。

举例:

SELECT x FROM t1 WHERE x [NOT] IN (SELECT y FROM t2);
SELECT x FROM t1 WHERE EXISTS (SELECT y FROM t2 WHERE y = 1);

相关子查询

相关子查询支持[NOT] IN和[NOT] EXISTS。

举例:

SELECT * FROM t1 WHERE x [NOT] IN (SELECT a FROM t2 WHERE t1.y = t2.b);
SELECT * FROM t1 WHERE [NOT] EXISTS (SELECT a FROM t2 WHERE t1.y = t2.b);

子查询还支持标量子查询。分为不相关标量子查询、相关标量子查询和标量子查询作为普通函数的参数。

举例:

1、不相关标量子查询,谓词为=号。例如输出最大工资的人的信息
SELECT name FROM table WHERE salary = (SELECT MAX(salary) FROM table);
2、不相关标量子查询,谓词为>,<等。例如输出比平均工资高的人的信息
SELECT name FROM table WHERE salary > (SELECT AVG(salary) FROM table);
3、相关标量子查询。例如输出各个部门工资最高的信息
SELECT name FROM table a WHERE salary = (SELECT MAX(salary) FROM table b WHERE b.部门= a.部门);
4、标量子查询作为普通函数的参数
SELECT name FROM table WHERE salary = abs((SELECT MAX(salary) FROM table));

with子句

可以在SELECT语句之前添加的子句,用于定义在SELECT内部多次引用的复杂表达式的别名。与CREATE VIEW类似,除了在子句中定义的表和列名在查询结束后不会持久以及不会与实际表或VIEW中的名称冲突。

用WITH子句的好处有:

1.方便和易于维护,减少查询内部的重复。

2.通过将查询中最复杂的部分抽象成单独的块,更易于阅读和理解SQL代码。

举例:

 -- Define one subquery at the outer level, and another at the inner level as part of the
 -- initial stage of the UNION ALL query.
 with t1 as (select 1) (with t2 as (select 2) select * from t2) union all select * from t1;

SHOW语句

Show alter

该语句用于展示当前正在进行的各类修改任务的执行情况.

语法:

 SHOW ALTER TABLE [COLUMN | ROLLUP] [FROM db_name];

说明:

  • TABLE COLUMN:展示修改列的ALTER任务
  • TABLE ROLLUP:展示创建或删除ROLLUP index的任务
  • 如果不指定 db_name,使用当前默认 db

举例:

1.展示默认 db 的所有修改列的任务执行情况

 SHOW ALTER TABLE COLUMN;

2.展示指定 db 的创建或删除 ROLLUP index 的任务执行情况

 SHOW ALTER TABLE ROLLUP FROM example_db;

Show data

该语句用于展示数据量

语法:

 SHOW DATA [FROM db_name[.table_name]];

说明:

如果不指定FROM子句,使用展示当前db下细分到各个 table的数据量。如果指定 FROM子句,则展示table下细分到各个index的数据量

举例:

1.展示默认db的各个table的数据量及汇总数据量

 SHOW DATA;

2.展示指定db的下指定表的细分数据量

 SHOW DATA FROM example_db.table_name;

Show databases

该语句用于展示当前可见的database

语法:

 SHOW DATABASES;

Show load

该语句用于展示指定的导入任务的执行情况

语法:

 SHOW LOAD    
 [FROM db_name]    
 [   
 WHERE    
 [LABEL [ = "your_label" | LIKE "label_matcher"]]    
 [STATUS = ["PENDING"|"ETL"|"LOADING"|"FINISHED"|"CANCELLED"|]]    
 ]    
 [ORDER BY ...]    
 [LIMIT limit];

说明:

  • 如果不指定 db_name,使用当前默认db
  • 如果使用 LABEL LIKE,则会匹配导入任务的 label 包含 label_matcher 的导入任务
  • 如果使用 LABEL = ,则精确匹配指定的 label
  • 如果指定了 STATUS,则匹配 LOAD 状态
  • 可以使用 ORDER BY 对任意列组合进行排序
  • 如果指定了 LIMIT,则显示 limit 条匹配记录。否则全部显示

举例:

1.展示默认 db 的所有导入任务

 SHOW LOAD;

2.展示指定 db 的导入任务,label 中包含字符串 "2014_01_02",展示最老的10个

 SHOW LOAD FROM example_db WHERE LABEL LIKE "2014_01_02" LIMIT 10;

3.展示指定 db 的导入任务,指定 label 为 "load_example_db_20140102" 并按 LoadStartTime 降序排序

 SHOW LOAD FROM example_db WHERE LABEL = "load_example_db_20140102" ORDER BY LoadStartTime DESC;

4.展示指定 db 的导入任务,指定 label 为 "load_example_db_20140102" ,state 为 "loading", 并按 LoadStartTime 降序排序

 SHOW LOAD FROM example_db WHERE LABEL = "load_example_db_20140102" AND STATE = "loading" ORDER BY LoadStartTime DESC;

Show export

该语句用于展示指定的导出任务的执行情况

语法:

 SHOW EXPORT
 [FROM db_name]
 [
 WHERE
 [EXPORT_JOB_ID = your_job_id]
 [STATE = ["PENDING"|"EXPORTING"|"FINISHED"|"CANCELLED"]]
 ]
 [ORDER BY ...]
 [LIMIT limit];

说明:

  • 如果不指定 db_name,使用当前默认db
  • 如果指定了 STATE,则匹配 EXPORT 状态
  • 可以使用 ORDER BY 对任意列组合进行排序
  • 如果指定了 LIMIT,则显示 limit 条匹配记录。否则全部显示

举例:

1.展示默认 db 的所有导出任务

SHOW EXPORT;

2.展示指定 db 的导出任务,按 StartTime 降序排序

SHOW EXPORT FROM example_db ORDER BY StartTime DESC;

3.展示指定 db 的导出任务,state 为 "exporting", 并按 StartTime 降序排序

SHOW EXPORT FROM example_db WHERE STATE = "exporting" ORDER BY StartTime DESC;

4.展示指定db,指定job_id的导出任务

SHOW EXPORT FROM example_db WHERE EXPORT_JOB_ID = job_id;

Show partitions

该语句用于展示分区信息

语法:

 SHOW PARTITIONS FROM [db_name.]table_name [PARTITION partition_name];

举例:

1.展示指定 db 下指定表的分区信息

 SHOW PARTITIONS FROM example_db.table_name;

2.展示指定 db 下指定表的指定分区的信息

 SHOW PARTITIONS FROM example_db.table_name PARTITION p1;

Show quota

该语句用于显示一个用户不同组的资源分配情况

语法:

 SHOW QUOTA FOR [user]

举例:

显示system用户的资源在各个组的分配情况

 SHOW QUOTA FOR system;

Show resource

该语句用于显示一个用户在不同资源上的权重

语法:

 SHOW RESOURCE [LIKE user_name]

举例:

显示system用户在不同资源上的权重

 SHOW RESOURCE LIKE "system";

Show tables

该语句用于展示当前db下所有的table

语法:

 SHOW TABLES;

Show tablet

该语句用于显示tablet相关的信息(仅管理员使用)

语法:

 SHOW TABLET [FROM [db_name.]table_name | tablet_id]

举例:

1.显示指定 db 的下指定表所有 tablet 信息

 SHOW TABLET FROM example_db.table_name;

2.显示指定 tablet id 为 10000 的 tablet 的父层级 id 信息

 SHOW TABLET 10000;

账户管理

Create user

该语句用来创建一个用户,需要管理员权限。如果在非default_cluster下create user,用户在登录连接doris和mini load等使用到用户名时,用户名将为user_name@cluster_name。如果在default_cluster下create user,用户在登录连接doris和mini load等使用到用户名时,用户名中不需要添加@cluster_name,即直接为user_name。

语法:

 CREATE USER user_specification [SUPERUSER]    
 user_specification:    
 'user_name' [IDENTIFIED BY [PASSWORD] 'password']

说明:

CREATE USER命令可用于创建一个doris用户,使用这个命令需要使用者必须有管理员权限。SUPERUSER用于指定需要创建的用户是个超级用户

举例:

1.创建一个没有密码的用户,用户名为 jack

 CREATE USER 'jack'

2.创建一个带有密码的用户,用户名为 jack,并且密码被指定为 123456

 CREATE USER 'jack' IDENTIFIED BY '123456'

3.为了避免传递明文,用例2也可以使用下面的方式来创建

 CREATE USER 'jack' IDENTIFIED BY PASSWORD '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9'

后面加密的内容可以通过PASSWORD()获得到,例如:

 SELECT PASSWORD('123456')

4.创建一个超级用户'jack'

 CREATE USER 'jack' SUPERUSER

Drop user

该语句用于删除一个用户,需要管理员权限

语法:

 DROP USER 'user_name'

举例:

删除用户 jack

DROP USER 'jack'

Alter user

该语句用于修改用户的相关属性以及分配给用户的资源

语法:

 ALTER USER user alter_user_clause_list    
 alter_user_clause_list:    
 alter_user_clause [, alter_user_clause] ...    
 alter_user_clause:   
 MODIFY RESOURCE resource value | MODIFY PROPERTY property value   
 resource:    
 CPU_SHARE   
 property:   
 MAX_USER_CONNECTIONS

举例:

1.修改用户jack的CPU_SHARE为1000

 ALTER USER jack MODIFY RESOURCE CPU_SHARE 1000

2.修改用户 jack 最大连接数为1000

 ALTER USER jack MODIFY PROPERTY MAX_USER_CONNECTIONS 1000

Alter quota

该语句用于修改某用户不同组资源的分配

语法:

 ALTER QUOTA FOR user_name MODIFY group_name value

举例:

修改system用户的normal组的权重

 ALTER QUOTA FOR system MODIFY normal 400;

Grant

该语句用于将一个数据库的具体权限授权给具体用户。调用者必须是管理员身份。权限当前只包括只读 (READ_ONLY),读写 (READ_WRITE) 两种权限,如果指定为ALL,那么就是将全部权限授予该用户。

语法:

 GRANT privilege_list ON db_name TO 'user_name'    
 privilege_list:   
 privilege [, privilege] ...    
 privilege:    
 READ_ONLY | READ_WRITE | ALL

举例:

1.授予用户 jack 数据库 testDb 的写权限

 GRANT READ_ONLY ON testDb to 'jack';

2.授予用户 jack 数据库 testDb 全部权限

 GRANT ALL ON testDb to 'jack';

Set password

该语句用于修改一个用户的登录密码。如果 [FOR 'user_name'] 字段不存在,那么修改当前用户的密码。PASSWORD() 方式输入的是明文密码; 而直接使用字符串,需要传递的是已加密的密码。如果修改其他用户的密码,需要具有管理员权限。

语法:

 SET PASSWORD [FOR 'user_name'] = [PASSWORD('plain password')]|['hashed password']

举例:

1.修改当前用户的密码为 123456

 SET PASSWORD = PASSWORD('123456')    
 SET PASSWORD = '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9'

2.修改用户 jack 的密码为 123456

 SET PASSWORD FOR 'jack' = PASSWORD('123456')    
 SET PASSWORD FOR 'jack' = '\*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9'

集群管理

Alter system

该语句用于操作一个集群内的节点。(仅管理员使用!)

语法:

 1.增加节点
     ALTER SYSTEM ADD BACKEND "host:heartbeat_port"[,"host:heartbeat_port"...];
 2.删除节点
     ALTER SYSTEM DROP BACKEND "host:heartbeat_port"[,"host:heartbeat_port"...];
 3.节点下线
     ALTER SYSTEM DECOMMISSION BACKEND "host:heartbeat_port"[,"host:heartbeat_port"...];
 4.增加Broker
     ALTER SYSTEM ADD BROKER broker_name "host:port"[,"host:port"...];
 5.减少Broker
     ALTER SYSTEM DROP BROKER broker_name "host:port"[,"host:port"...];
 6.删除所有Broker
     ALTER SYSTEM DROP ALL BROKER broker_name

说明:

  • host 可以是主机名或者ip地址
  • heartbeat_port 为该节点的心跳端口
  • 加和删除节点为同步操作。这两种操作不考虑节点上已有的数据,节点直接从元数据中删除,请谨慎使用。
  • 点下线操作用于安全下线节点。该操作为异步操作。如果成功,节点最终会从元数据中删除。如果失败,则不会完成下线。
  • 可以手动取消节点下线操作。详见 CANCEL ALTER SYSTEM

举例:

1.增加一个节点

 ALTER SYSTEM ADD BACKEND "host:9850";

2.删除两个节点

 ALTER SYSTEM DROP BACKEND "host1:9850", "host2:9850";

3.下线两个节点

 ALTER SYSTEM DECOMMISSION BACKEND "host1:9850", "host2:9850";

4.增加两个Hdfs Broker

 ALTER SYSTEM ADD BROKER hdfs "host1:9850", "host2:9850";

Cancel alter system

该语句用于撤销一个节点下线操作。(仅管理员使用!)

语法:

 CANCEL ALTER SYSTEM DECOMMISSION BACKEND "host:heartbeat_port"[,"host:heartbeat_port"...];

举例:

1.取消两个节点的下线操作

 CANCEL ALTER SYSTEM DECOMMISSION BACKEND "host1:9850", "host2:9850";

Create cluster

该语句用于新建逻辑集群 (cluster), 需要管理员权限。如果不使用多租户,直接创建一个名称为default_cluster的cluster。否则创建一个自定义名称的cluster。

语法:

 CREATE CLUSTER [IF NOT EXISTS] cluster_name
 PROPERTIES ("key"="value", ...)
 IDENTIFIED BY 'password'

PROPERTIES

指定逻辑集群的属性。PROERTIES ("instance_num" = "3")。其中instance_num是逻辑集群节点数。

identified by ‘password'

每个逻辑集群含有一个superuser,创建逻辑集群时必须指定其密码

举例:

1.新建一个含有3个be节点逻辑集群 test_cluster, 并指定其superuser用户密码

 CREATE CLUSTER test_cluster PROPERTIES("instance_num"="3") IDENTIFIED BY 'test';

2.新建一个含有3个be节点逻辑集群 default_cluster(不使用多租户), 并指定其superuser用户密码

 CREATE CLUSTER default_cluster PROPERTIES("instance_num"="3") IDENTIFIED BY 'test';

Alter cluster

该语句用于更新逻辑集群。需要有管理员权限

语法:

 ALTER CLUSTER cluster_name PROPERTIES ("key"="value", ...);

PROPERTIES

缩容,扩容 (根据集群现有的be数目,大则为扩容,小则为缩容), 扩容为同步操作,缩容为异步操作,通过backend的状态可以得知是否缩容完成。PROERTIES ("instance_num" = "3")。其中instance_num是逻辑集群节点数。

举例:

1.缩容,减少含有3个be的逻辑集群test_cluster的be数为2

 ALTER CLUSTER test_cluster PROPERTIES ("instance_num"="2");

2.扩容,增加含有3个be的逻辑集群test_cluster的be数为4

 ALTER CLUSTER test_cluster PROPERTIES ("instance_num"="4");

Drop cluster

该语句用于删除逻辑集群,成功删除逻辑集群需要首先删除集群内的db,需要管理员权限

语法:

 DROP CLUSTER [IF EXISTS] cluster_name;
别名注释