Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
taosdata
TDengine
提交
a9ab3c89
T
TDengine
项目概览
taosdata
/
TDengine
1 年多 前同步成功
通知
1185
Star
22016
Fork
4786
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
T
TDengine
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1
Issue
1
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
a9ab3c89
编写于
4月 24, 2022
作者:
X
Xiaoyu Wang
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
enh: order by primary key optimize
上级
d16a2e27
变更
4
显示空白变更内容
内联
并排
Showing
4 changed file
with
159 addition
and
37 deletion
+159
-37
source/libs/parser/inc/sql.y
source/libs/parser/inc/sql.y
+1
-0
source/libs/parser/src/parCalcConst.c
source/libs/parser/src/parCalcConst.c
+1
-1
source/libs/planner/src/planOptimizer.c
source/libs/planner/src/planOptimizer.c
+146
-27
source/libs/scalar/src/sclfunc.c
source/libs/scalar/src/sclfunc.c
+11
-9
未找到文件。
source/libs/parser/inc/sql.y
浏览文件 @
a9ab3c89
...
...
@@ -611,6 +611,7 @@ function_expression(A) ::= function_name(B) NK_LP expression_list(C) NK_RP(D).
function_expression(A) ::= star_func(B) NK_LP star_func_para_list(C) NK_RP(D). { A = createRawExprNodeExt(pCxt, &B, &D, createFunctionNode(pCxt, &B, C)); }
function_expression(A) ::= CAST(B) NK_LP expression(C) AS type_name(D) NK_RP(E). { A = createRawExprNodeExt(pCxt, &B, &E, createCastFunctionNode(pCxt, releaseRawExprNode(pCxt, C), D)); }
function_expression(A) ::= noarg_func(B) NK_LP NK_RP(C). { A = createRawExprNodeExt(pCxt, &B, &C, createFunctionNodeNoArg(pCxt, &B)); }
//function_expression(A) ::= NOW(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); }
%type noarg_func { SToken }
%destructor noarg_func { }
...
...
source/libs/parser/src/parCalcConst.c
浏览文件 @
a9ab3c89
...
...
@@ -83,7 +83,7 @@ static EDealRes calcConstOperator(SOperatorNode** pNode, void* pContext) {
static
EDealRes
calcConstFunction
(
SFunctionNode
**
pNode
,
void
*
pContext
)
{
SFunctionNode
*
pFunc
=
*
pNode
;
if
(
!
fmIsScalarFunc
(
pFunc
->
funcId
))
{
if
(
!
fmIsScalarFunc
(
pFunc
->
funcId
)
||
fmIsUserDefinedFunc
(
pFunc
->
funcId
)
)
{
return
DEAL_RES_CONTINUE
;
}
SNode
*
pParam
=
NULL
;
...
...
source/libs/planner/src/planOptimizer.c
浏览文件 @
a9ab3c89
...
...
@@ -20,6 +20,8 @@
#define OPTIMIZE_FLAG_MASK(n) (1 << n)
#define OPTIMIZE_FLAG_OSD OPTIMIZE_FLAG_MASK(0)
#define OPTIMIZE_FLAG_CPD OPTIMIZE_FLAG_MASK(1)
#define OPTIMIZE_FLAG_OPK OPTIMIZE_FLAG_MASK(2)
#define OPTIMIZE_FLAG_SET_MASK(val, mask) (val) |= (mask)
#define OPTIMIZE_FLAG_TEST_MASK(val, mask) (((val) & (mask)) != 0)
...
...
@@ -57,7 +59,23 @@ typedef enum ECondAction {
// after supporting outer join, there are other possibilities
}
ECondAction
;
EDealRes
haveNormalColImpl
(
SNode
*
pNode
,
void
*
pContext
)
{
typedef
bool
(
*
FMayBeOptimized
)(
SLogicNode
*
pNode
);
static
SLogicNode
*
optFindPossibleNode
(
SLogicNode
*
pNode
,
FMayBeOptimized
func
)
{
if
(
func
(
pNode
))
{
return
pNode
;
}
SNode
*
pChild
;
FOREACH
(
pChild
,
pNode
->
pChildren
)
{
SLogicNode
*
pScanNode
=
optFindPossibleNode
((
SLogicNode
*
)
pChild
,
func
);
if
(
NULL
!=
pScanNode
)
{
return
pScanNode
;
}
}
return
NULL
;
}
EDealRes
osdHaveNormalColImpl
(
SNode
*
pNode
,
void
*
pContext
)
{
if
(
QUERY_NODE_COLUMN
==
nodeType
(
pNode
))
{
*
((
bool
*
)
pContext
)
=
(
COLUMN_TYPE_TAG
!=
((
SColumnNode
*
)
pNode
)
->
colType
);
return
*
((
bool
*
)
pContext
)
?
DEAL_RES_END
:
DEAL_RES_IGNORE_CHILD
;
...
...
@@ -65,9 +83,9 @@ EDealRes haveNormalColImpl(SNode* pNode, void* pContext) {
return
DEAL_RES_CONTINUE
;
}
static
bool
h
aveNormalCol
(
SNodeList
*
pList
)
{
static
bool
osdH
aveNormalCol
(
SNodeList
*
pList
)
{
bool
res
=
false
;
nodesWalkExprsPostOrder
(
pList
,
h
aveNormalColImpl
,
&
res
);
nodesWalkExprsPostOrder
(
pList
,
osdH
aveNormalColImpl
,
&
res
);
return
res
;
}
...
...
@@ -89,21 +107,7 @@ static bool osdMayBeOptimized(SLogicNode* pNode) {
if
(
QUERY_NODE_LOGIC_PLAN_WINDOW
==
nodeType
(
pNode
->
pParent
))
{
return
(
WINDOW_TYPE_INTERVAL
==
((
SWindowLogicNode
*
)
pNode
->
pParent
)
->
winType
);
}
return
!
haveNormalCol
(((
SAggLogicNode
*
)
pNode
->
pParent
)
->
pGroupKeys
);
}
static
SLogicNode
*
osdFindPossibleScanNode
(
SLogicNode
*
pNode
)
{
if
(
osdMayBeOptimized
(
pNode
))
{
return
pNode
;
}
SNode
*
pChild
;
FOREACH
(
pChild
,
pNode
->
pChildren
)
{
SLogicNode
*
pScanNode
=
osdFindPossibleScanNode
((
SLogicNode
*
)
pChild
);
if
(
NULL
!=
pScanNode
)
{
return
pScanNode
;
}
}
return
NULL
;
return
!
osdHaveNormalCol
(((
SAggLogicNode
*
)
pNode
->
pParent
)
->
pGroupKeys
);
}
static
SNodeList
*
osdGetAllFuncs
(
SLogicNode
*
pNode
)
{
...
...
@@ -138,7 +142,7 @@ static int32_t osdGetRelatedFuncs(SScanLogicNode* pScan, SNodeList** pSdrFuncs,
}
static
int32_t
osdMatch
(
SOptimizeContext
*
pCxt
,
SLogicNode
*
pLogicNode
,
SOsdInfo
*
pInfo
)
{
pInfo
->
pScan
=
(
SScanLogicNode
*
)
o
sdFindPossibleScanNode
(
pLogicNode
);
pInfo
->
pScan
=
(
SScanLogicNode
*
)
o
ptFindPossibleNode
(
pLogicNode
,
osdMayBeOptimized
);
if
(
NULL
==
pInfo
->
pScan
)
{
return
TSDB_CODE_SUCCESS
;
}
...
...
@@ -345,7 +349,7 @@ static int32_t cpdCalcTimeRange(SScanLogicNode* pScan, SNode** pPrimaryKeyCond,
}
static
int32_t
cpdOptimizeScanCondition
(
SOptimizeContext
*
pCxt
,
SScanLogicNode
*
pScan
)
{
if
(
NULL
==
pScan
->
node
.
pConditions
)
{
if
(
NULL
==
pScan
->
node
.
pConditions
||
OPTIMIZE_FLAG_TEST_MASK
(
pScan
->
node
.
optimizedFlag
,
OPTIMIZE_FLAG_CPD
)
)
{
return
TSDB_CODE_SUCCESS
;
}
...
...
@@ -359,7 +363,10 @@ static int32_t cpdOptimizeScanCondition(SOptimizeContext* pCxt, SScanLogicNode*
pScan
->
node
.
pConditions
=
pOtherCond
;
}
if
(
TSDB_CODE_SUCCESS
!=
code
)
{
if
(
TSDB_CODE_SUCCESS
==
code
)
{
OPTIMIZE_FLAG_SET_MASK
(
pScan
->
node
.
optimizedFlag
,
OPTIMIZE_FLAG_CPD
);
pCxt
->
optimized
=
true
;
}
else
{
nodesDestroyNode
(
pPrimaryKeyCond
);
nodesDestroyNode
(
pOtherCond
);
}
...
...
@@ -367,7 +374,7 @@ static int32_t cpdOptimizeScanCondition(SOptimizeContext* pCxt, SScanLogicNode*
return
code
;
}
static
bool
b
elongThisTable
(
SNode
*
pCondCol
,
SNodeList
*
pTableCols
)
{
static
bool
cpdB
elongThisTable
(
SNode
*
pCondCol
,
SNodeList
*
pTableCols
)
{
SNode
*
pTableCol
=
NULL
;
FOREACH
(
pTableCol
,
pTableCols
)
{
if
(
nodesEqualNode
(
pCondCol
,
pTableCol
))
{
...
...
@@ -380,9 +387,9 @@ static bool belongThisTable(SNode* pCondCol, SNodeList* pTableCols) {
static
EDealRes
cpdIsMultiTableCondImpl
(
SNode
*
pNode
,
void
*
pContext
)
{
SCpdIsMultiTableCondCxt
*
pCxt
=
pContext
;
if
(
QUERY_NODE_COLUMN
==
nodeType
(
pNode
))
{
if
(
b
elongThisTable
(
pNode
,
pCxt
->
pLeftCols
))
{
if
(
cpdB
elongThisTable
(
pNode
,
pCxt
->
pLeftCols
))
{
pCxt
->
havaLeftCol
=
true
;
}
else
if
(
b
elongThisTable
(
pNode
,
pCxt
->
pRightCols
))
{
}
else
if
(
cpdB
elongThisTable
(
pNode
,
pCxt
->
pRightCols
))
{
pCxt
->
haveRightCol
=
true
;
}
return
pCxt
->
havaLeftCol
&&
pCxt
->
haveRightCol
?
DEAL_RES_END
:
DEAL_RES_CONTINUE
;
...
...
@@ -509,7 +516,7 @@ static int32_t cpdPushCondToChild(SOptimizeContext* pCxt, SLogicNode* pChild, SN
}
static
int32_t
cpdPushJoinCondition
(
SOptimizeContext
*
pCxt
,
SJoinLogicNode
*
pJoin
)
{
if
(
NULL
==
pJoin
->
node
.
pConditions
)
{
if
(
NULL
==
pJoin
->
node
.
pConditions
||
OPTIMIZE_FLAG_TEST_MASK
(
pJoin
->
node
.
optimizedFlag
,
OPTIMIZE_FLAG_CPD
)
)
{
return
TSDB_CODE_SUCCESS
;
}
...
...
@@ -527,7 +534,10 @@ static int32_t cpdPushJoinCondition(SOptimizeContext* pCxt, SJoinLogicNode* pJoi
code
=
cpdPushCondToChild
(
pCxt
,
(
SLogicNode
*
)
nodesListGetNode
(
pJoin
->
node
.
pChildren
,
1
),
&
pRightChildCond
);
}
if
(
TSDB_CODE_SUCCESS
!=
code
)
{
if
(
TSDB_CODE_SUCCESS
==
code
)
{
OPTIMIZE_FLAG_SET_MASK
(
pJoin
->
node
.
optimizedFlag
,
OPTIMIZE_FLAG_CPD
);
pCxt
->
optimized
=
true
;
}
else
{
nodesDestroyNode
(
pOnCond
);
nodesDestroyNode
(
pLeftChildCond
);
nodesDestroyNode
(
pRightChildCond
);
...
...
@@ -572,9 +582,118 @@ static int32_t cpdOptimize(SOptimizeContext* pCxt, SLogicNode* pLogicNode) {
return
cpdPushCondition
(
pCxt
,
pLogicNode
);
}
static
bool
opkIsPrimaryKeyOrderBy
(
SNodeList
*
pSortKeys
)
{
if
(
1
!=
LIST_LENGTH
(
pSortKeys
))
{
return
false
;
}
SNode
*
pNode
=
nodesListGetNode
(
pSortKeys
,
0
);
return
(
QUERY_NODE_COLUMN
==
nodeType
(
pNode
)
?
(
PRIMARYKEY_TIMESTAMP_COL_ID
==
((
SColumnNode
*
)
pNode
)
->
colId
)
:
false
);
}
static
bool
opkSortMayBeOptimized
(
SLogicNode
*
pNode
)
{
if
(
QUERY_NODE_LOGIC_PLAN_SORT
!=
nodeType
(
pNode
))
{
return
false
;
}
if
(
OPTIMIZE_FLAG_TEST_MASK
(
pNode
->
optimizedFlag
,
OPTIMIZE_FLAG_OPK
))
{
return
false
;
}
return
true
;
}
static
int32_t
opkGetScanNodesImpl
(
SLogicNode
*
pNode
,
bool
*
pNotOptimize
,
SNodeList
**
pScanNodes
)
{
int32_t
code
=
TSDB_CODE_SUCCESS
;
switch
(
nodeType
(
pNode
))
{
case
QUERY_NODE_LOGIC_PLAN_SCAN
:
return
nodesListMakeAppend
(
pScanNodes
,
pNode
);
case
QUERY_NODE_LOGIC_PLAN_JOIN
:
code
=
opkGetScanNodesImpl
(
nodesListGetNode
(
pNode
->
pChildren
,
0
),
pNotOptimize
,
pScanNodes
);
if
(
TSDB_CODE_SUCCESS
==
code
)
{
code
=
opkGetScanNodesImpl
(
nodesListGetNode
(
pNode
->
pChildren
,
1
),
pNotOptimize
,
pScanNodes
);
}
return
code
;
case
QUERY_NODE_LOGIC_PLAN_AGG
:
*
pNotOptimize
=
true
;
return
code
;
default:
break
;
}
if
(
1
!=
LIST_LENGTH
(
pNode
->
pChildren
))
{
*
pNotOptimize
=
true
;
}
return
opkGetScanNodesImpl
(
nodesListGetNode
(
pNode
->
pChildren
,
0
),
pNotOptimize
,
pScanNodes
);
}
static
int32_t
opkGetScanNodes
(
SLogicNode
*
pNode
,
SNodeList
**
pScanNodes
)
{
bool
notOptimize
=
false
;
int32_t
code
=
opkGetScanNodesImpl
(
pNode
,
&
notOptimize
,
pScanNodes
);
if
(
TSDB_CODE_SUCCESS
!=
code
||
notOptimize
)
{
nodesClearList
(
*
pScanNodes
);
}
return
code
;
}
static
EOrder
opkGetPrimaryKeyOrder
(
SSortLogicNode
*
pSort
)
{
return
((
SOrderByExprNode
*
)
nodesListGetNode
(
pSort
->
pSortKeys
,
0
))
->
order
;
}
static
SNode
*
opkRewriteDownNode
(
SSortLogicNode
*
pSort
)
{
SNode
*
pDownNode
=
nodesListGetNode
(
pSort
->
node
.
pChildren
,
0
);
// todo
return
pDownNode
;
}
static
int32_t
opkDoOptimized
(
SOptimizeContext
*
pCxt
,
SSortLogicNode
*
pSort
,
SNodeList
*
pScanNodes
)
{
EOrder
order
=
opkGetPrimaryKeyOrder
(
pSort
);
SNode
*
pScan
=
NULL
;
FOREACH
(
pScan
,
pScanNodes
)
{
((
SScanLogicNode
*
)
pScan
)
->
scanFlag
=
(
ORDER_ASC
==
order
?
MAIN_SCAN
:
REVERSE_SCAN
);
}
if
(
NULL
==
pSort
->
node
.
pParent
)
{
// todo
return
TSDB_CODE_SUCCESS
;
}
SNode
*
pDownNode
=
opkRewriteDownNode
(
pSort
);
SNode
*
pNode
;
FOREACH
(
pNode
,
pSort
->
node
.
pParent
->
pChildren
)
{
if
(
nodesEqualNode
(
pNode
,
pSort
))
{
REPLACE_NODE
(
pDownNode
);
break
;
}
}
nodesDestroyNode
(
pSort
);
return
TSDB_CODE_SUCCESS
;
}
static
int32_t
opkOptimizeImpl
(
SOptimizeContext
*
pCxt
,
SSortLogicNode
*
pSort
)
{
OPTIMIZE_FLAG_SET_MASK
(
pSort
->
node
.
optimizedFlag
,
OPTIMIZE_FLAG_OPK
);
if
(
!
opkIsPrimaryKeyOrderBy
(
pSort
->
pSortKeys
)
||
1
!=
LIST_LENGTH
(
pSort
->
node
.
pChildren
))
{
return
TSDB_CODE_SUCCESS
;
}
SNodeList
*
pScanNodes
=
NULL
;
int32_t
code
=
opkGetScanNodes
(
nodesListGetNode
(
pSort
->
node
.
pChildren
,
0
),
&
pScanNodes
);
if
(
TSDB_CODE_SUCCESS
==
code
&&
NULL
!=
pScanNodes
)
{
code
=
opkDoOptimized
(
pCxt
,
pSort
,
pScanNodes
);
}
nodesClearList
(
pScanNodes
);
return
code
;
}
static
int32_t
opkOptimize
(
SOptimizeContext
*
pCxt
,
SLogicNode
*
pLogicNode
)
{
SSortLogicNode
*
pSort
=
(
SSortLogicNode
*
)
optFindPossibleNode
(
pLogicNode
,
opkSortMayBeOptimized
);
if
(
NULL
==
pSort
)
{
return
TSDB_CODE_SUCCESS
;
}
return
opkOptimizeImpl
(
pCxt
,
pSort
);
}
static
const
SOptimizeRule
optimizeRuleSet
[]
=
{
{
.
pName
=
"OptimizeScanData"
,
.
optimizeFunc
=
osdOptimize
},
{
.
pName
=
"ConditionPushDown"
,
.
optimizeFunc
=
cpdOptimize
}
{
.
pName
=
"ConditionPushDown"
,
.
optimizeFunc
=
cpdOptimize
},
{
.
pName
=
"OrderByPrimaryKey"
,
.
optimizeFunc
=
opkOptimize
}
};
static
const
int32_t
optimizeRuleNum
=
(
sizeof
(
optimizeRuleSet
)
/
sizeof
(
SOptimizeRule
));
...
...
source/libs/scalar/src/sclfunc.c
浏览文件 @
a9ab3c89
...
...
@@ -1247,26 +1247,28 @@ int32_t timeDiffFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *p
}
int32_t
nowFunction
(
SScalarParam
*
pInput
,
int32_t
inputNum
,
SScalarParam
*
pOutput
)
{
if
(
inputNum
!=
1
)
{
return
TSDB_CODE_FAILED
;
int64_t
ts
=
taosGetTimestamp
(
TSDB_TIME_PRECISION_MILLI
);
for
(
int32_t
i
=
0
;
i
<
pInput
->
numOfRows
;
++
i
)
{
colDataAppendInt64
(
pOutput
->
columnData
,
i
,
&
ts
);
}
colDataAppendInt64
(
pOutput
->
columnData
,
pOutput
->
numOfRows
,
(
int64_t
*
)
colDataGetData
(
pInput
->
columnData
,
0
))
;
pOutput
->
numOfRows
=
pInput
->
numOfRows
;
return
TSDB_CODE_SUCCESS
;
}
int32_t
todayFunction
(
SScalarParam
*
pInput
,
int32_t
inputNum
,
SScalarParam
*
pOutput
)
{
if
(
inputNum
!=
1
)
{
return
TSDB_CODE_FAILED
;
int64_t
ts
=
taosGetTimestampToday
(
TSDB_TIME_PRECISION_MILLI
);
for
(
int32_t
i
=
0
;
i
<
pInput
->
numOfRows
;
++
i
)
{
colDataAppendInt64
(
pOutput
->
columnData
,
i
,
&
ts
);
}
colDataAppendInt64
(
pOutput
->
columnData
,
pOutput
->
numOfRows
,
(
int64_t
*
)
colDataGetData
(
pInput
->
columnData
,
0
))
;
pOutput
->
numOfRows
=
pInput
->
numOfRows
;
return
TSDB_CODE_SUCCESS
;
}
int32_t
timezoneFunction
(
SScalarParam
*
pInput
,
int32_t
inputNum
,
SScalarParam
*
pOutput
)
{
if
(
inputNum
!=
1
)
{
return
TSDB_CODE_FAILED
;
for
(
int32_t
i
=
0
;
i
<
pInput
->
numOfRows
;
++
i
)
{
colDataAppend
(
pOutput
->
columnData
,
i
,
tsTimezoneStr
,
false
)
;
}
colDataAppend
(
pOutput
->
columnData
,
pOutput
->
numOfRows
,
(
char
*
)
colDataGetData
(
pInput
->
columnData
,
0
),
false
)
;
pOutput
->
numOfRows
=
pInput
->
numOfRows
;
return
TSDB_CODE_SUCCESS
;
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录