SELECT 概况#

Syntax#

SelectStmt#

SelectStmt
         ::= WithClause ( NoTableSelectClause | SelectStmtFromTable) 

WithClause
         ::= 'WITH' non_recursive_cte [, ...]

non_recursive_cte
         ::= cte_name 'AS' '(' SelectStmt ')'

NoTableSelectClause
         ::= 'SELECT' SelectExprList      

SelectStmtFromTable
         ::= SelectStmtBasic 'FROM' TableRefs [WhereClause] [GroupByClause] [HavingClause] [WindowClause] [OrderByClause] [LimitClause]
           
JoinClause
         ::= TableRef JoinType 'JOIN' TableRef [OrderClause] 'ON' Expression 
JoinType ::= 'LAST'           
         
WhereClause
         ::= 'WHERE' Expression
         
GroupByClause
         ::= 'GROUP' 'BY' ByList

HavingClause
         ::= 'HAVING' Expression 
         
WindowClause
         ::= ( 'WINDOW' WindowDefinition ( ',' WindowDefinition )* )   
         
OrderByClause  ::= 'ORDER' 'BY' ByList   

ByList   ::= ByItem ( ',' ByItem )*

ByItem   ::= Expression Order

Order    ::= ( 'ASC' | 'DESC' )?

WindowClauseOptional
         ::= ( 'WINDOW' WindowDefinition ( ',' WindowDefinition )* )?
WindowDefinition
         ::= WindowName 'AS' WindowSpec

WindowSpec
         ::= '(' WindowSpecDetails ')'   
         
WindowSpecDetails
         ::= [ExistingWindowName] [WindowUnionClause] WindowPartitionClause WindowOrderByClause WindowFrameClause (WindowAttribute)*

WindowUnionClause
        :: = ( 'UNION' TableRefs)

WindowPartitionClause
         ::= ( 'PARTITION' 'BY' ByList ) 

WindowOrderByClause
        ::= ( 'ORDER' 'BY' ByList )

WindowFrameClause
        ::= ( WindowFrameUnits WindowFrameBounds [WindowFrameMaxSize] )

WindowFrameUnits
        ::= 'ROWS'
          | 'ROWS_RANGE'

WindowFrameBounds
        ::= 'BETWEEN' WindowFrameBound 'AND' WindowFrameBound

WindowFrameBound
        ::= ( 'UNBOUNDED' | NumLiteral | IntervalLiteral ) ['OPEN'] 'PRECEDING'
          | 'CURRENT' 'ROW'

WindowAttribute
        ::= WindowExcludeCurrentTime
          | WindowExcludeCurrentRow
          | WindowInstanceNotInWindow

WindowExcludeCurrentTime
        ::= 'EXCLUDE' 'CURRENT_TIME'

WindowExcludeCurrentRow
        ::= 'EXCLUDE' 'CURRENT_ROW'

WindowInstanceNotInWindow
        :: = 'INSTANCE_NOT_IN_WINDOW'

WindowFrameMaxSize
        :: = 'MAXSIZE' NumLiteral

SelectExprList#

SelectExprList
         ::= SelectExpr ( ',' SelectExpr )*
SelectExpr    ::= ( Identifier '.' ( Identifier '.' )? )? '*'
           | ( Expression | '{' Identifier Expression '}' ) ['AS' Identifier]
                      

TableRefs#

TableRefs
         ::= EscapedTableRef ( ',' EscapedTableRef )*
TableRef ::= TableFactor
           | JoinClause
TableFactor
         ::= TableName [TableAsName]
           | '(' ( ( SelectStmt ) ')' TableAsName | TableRefs ')' )
TableAsName
         ::= 'AS'? Identifier

SELECT语句元素#

SELECT语句元素

离线模式

在线预览模式

在线请求模式

说明

SELECT Clause

投影操作列表,一般包括列名、表达式,或者是用 * 表示全部列

FROM Clause

表示数据来源,数据来源可以是一个表(select * from t;)或者是多个表 LAST JOIN (见JOIN 子句) 或者是0个表 ( select 1+1;),详见NO_TABLE SELECT

JOIN Clause

x

表示数据来源多个表JOIN。OpenMLDB目前仅支持LAST JOIN。在线请求模式下,需要遵循Online Request下LAST JOIN的使用规范

WHERE Clause

Where 子句用于设置过滤条件,查询结果中只会包含满足条件的数据。

GROUP BY Clause

Group By 子句用于对查询结果集进行分组。分组表达式列表仅支持简单列。

HAVING Clause

Having 子句与 Where 子句作用类似.Having 子句过滤 GroupBy 后的各种数据,Where 子句在聚合前进行过滤。

WINDOW Clause

窗口子句用于定义一个或者若干个窗口。窗口可以是有名或者匿名的。用户可以在窗口上调用聚合函数来进行一些分析型计算的操作(sql agg_func() over window_name)。线请求模式下,需要遵循Online Request下Window的使用规范

LIMIT Clause

Limit子句用于限制返回的结果条数。目前Limit仅支持接受一个参数,表示返回数据的最大行数。

ORDER BY Clause

标准SQL还支持Order By子句。OpenMLDB目前尚未支持Order子句。例如,查询语句SELECT * from t1 ORDER BY col1;在OpenMLDB中不被支持。

Warning

在线模式或单机版的select,可能无法获取完整数据。 因为一次查询可能在多台tablet 上进行大量的扫描,为了tablet 的稳定性,单个tablet 限制了最大扫描数据量,即scan_max_bytes_size

如果出现select结果截断,tablet 会出现reach the max byte ...的日志,但查询不会报错。

在线模式或单机版都不适合做大数据的扫描,推荐使用集群版的离线模式。如果一定要调大扫描量,需要对每台tablet配置--scan_max_bytes_size=xxx,并重启tablet生效。

离线同步模式 SELECT#

设置SET @@sync_job=true后的SELECT语句,就是离线同步模式下的SELECT。在这个状态下的SELECT会展示结果到CLI(不建议在SDK中使用这种模式,不会得到正常的ResultSet)。

原理:SELECT执行完成后各worker通过HTTP发送结果到TaskManager,TaskManager收集各个结果分片并保存到本地文件系统中。结果收集完成后,再从本地文件系统读取,读取后删除本地缓存的结果。

Attention

离线同步模式 SELECT 仅用于展示,不保证结果完整。整个结果收集中可能出现文件写入失败,丢失HTTP包等问题,我们允许结果缺失。

相关配置参数#

TaskManager配置batch.job.result.max.wait.time,在SELECT job完成后,我们会等待所有结果被收集并保存在TaskManager所在主机的文件系统中,超过这一时间将结束等待,返回错误。如果认为整个收集结果的过程没有问题,仅仅是等待时间不够,可以调大这一配置项,单位为ms,默认为10min。

Batch配置(spark.default.conf):

  • spark.openmldb.savejobresult.rowperpost: 为了防止HTTP传送过多数据,我们对数据进行切割,默认为16000行。如果单行数据量较大,可以调小该值。

  • spark.openmldb.savejobresult.posttimeouts: HTTP传送数据的超时配置,共三个超时配置项,用,分隔,分别为ConnectionRequestTimeout,ConnectTimeout,SocketTimeout,默认为10000,10000,10000。如果出现HTTP传输超时,可调整这一参数。

重置#

如果使用过程中出现错误,可能导致Result Id无法正确重置。所有Result Id都被虚假占用时,会出现错误”too much running jobs to save job result, reject this spark job”。这时可以通过HTTP请求TaskManager来重置,POST内容如下:

curl -H "Content-Type:application/json" http://0.0.0.0:9902/openmldb.taskmanager.TaskManagerServer/SaveJobResult -X POST -d '{"result_id":-1, "json_data": "reset"}'