Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
2dot5
ClickHouse
提交
cfc5b313
C
ClickHouse
项目概览
2dot5
/
ClickHouse
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
ClickHouse
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
cfc5b313
编写于
3月 27, 2015
作者:
A
Alexey Milovidov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
dbms: fixed 'force_index_by_date' setting [#METR-15484].
上级
048eed94
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
99 addition
and
45 deletion
+99
-45
dbms/include/DB/Storages/MergeTree/PKCondition.h
dbms/include/DB/Storages/MergeTree/PKCondition.h
+44
-36
dbms/src/Storages/MergeTree/MergeTreeDataSelectExecutor.cpp
dbms/src/Storages/MergeTree/MergeTreeDataSelectExecutor.cpp
+2
-2
dbms/src/Storages/MergeTree/PKCondition.cpp
dbms/src/Storages/MergeTree/PKCondition.cpp
+53
-7
未找到文件。
dbms/include/DB/Storages/MergeTree/PKCondition.h
浏览文件 @
cfc5b313
...
...
@@ -124,7 +124,7 @@ struct Range
private:
static
bool
equals
(
const
Field
&
lhs
,
const
Field
&
rhs
)
{
return
apply_visitor
(
FieldVisitorAccurateEquals
(),
lhs
,
rhs
);
}
static
bool
less
(
const
Field
&
lhs
,
const
Field
&
rhs
)
{
return
apply_visitor
(
FieldVisitorAccurateLess
(),
lhs
,
rhs
);
}
public:
Field
left
;
/// левая граница, если есть
Field
right
;
/// правая граница, если есть
...
...
@@ -132,17 +132,17 @@ public:
bool
right_bounded
;
/// ограничен ли справа
bool
left_included
;
/// включает левую границу, если есть
bool
right_included
;
/// включает правую границу, если есть
/// Всё множество.
Range
()
:
left
(),
right
(),
left_bounded
(
false
),
right_bounded
(
false
),
left_included
(
false
),
right_included
(
false
)
{}
/// Одна точка.
Range
(
const
Field
&
point
)
:
left
(
point
),
right
(
point
),
left_bounded
(
true
),
right_bounded
(
true
),
left_included
(
true
),
right_included
(
true
)
{}
/// Ограниченный с двух сторон диапазон.
Range
(
const
Field
&
left_
,
bool
left_included_
,
const
Field
&
right_
,
bool
right_included_
)
:
left
(
left_
),
right
(
right_
),
left_bounded
(
true
),
right_bounded
(
true
),
left_included
(
left_included_
),
right_included
(
right_included_
)
{}
static
Range
createRightBounded
(
const
Field
&
right_point
,
bool
right_included
)
{
Range
r
;
...
...
@@ -151,7 +151,7 @@ public:
r
.
right_included
=
right_included
;
return
r
;
}
static
Range
createLeftBounded
(
const
Field
&
left_point
,
bool
left_included
)
{
Range
r
;
...
...
@@ -160,7 +160,7 @@ public:
r
.
left_included
=
left_included
;
return
r
;
}
/// Установить левую границу.
void
setLeft
(
const
Field
&
point
,
bool
included
)
{
...
...
@@ -168,7 +168,7 @@ public:
left_bounded
=
true
;
left_included
=
included
;
}
/// Установить правую границу.
void
setRight
(
const
Field
&
point
,
bool
included
)
{
...
...
@@ -176,13 +176,13 @@ public:
right_bounded
=
true
;
right_included
=
included
;
}
/// x входит в range
bool
contains
(
const
Field
&
x
)
const
{
return
!
leftThan
(
x
)
&&
!
rightThan
(
x
);
}
/// x находится левее
bool
rightThan
(
const
Field
&
x
)
const
{
...
...
@@ -190,7 +190,7 @@ public:
?
!
(
less
(
left
,
x
)
||
(
left_included
&&
equals
(
x
,
left
)))
:
false
);
}
/// x находится правее
bool
leftThan
(
const
Field
&
x
)
const
{
...
...
@@ -198,7 +198,7 @@ public:
?
!
(
less
(
x
,
right
)
||
(
right_included
&&
equals
(
x
,
right
)))
:
false
);
}
bool
intersectsRange
(
const
Range
&
r
)
const
{
/// r левее меня.
...
...
@@ -219,7 +219,7 @@ public:
return
true
;
}
bool
containsRange
(
const
Range
&
r
)
const
{
/// r начинается левее меня.
...
...
@@ -242,49 +242,57 @@ public:
return
true
;
}
String
toString
()
const
{
std
::
stringstream
str
;
if
(
!
left_bounded
)
str
<<
"(-inf, "
;
else
str
<<
(
left_included
?
'['
:
'('
)
<<
apply_visitor
(
FieldVisitorToString
(),
left
)
<<
", "
;
if
(
!
right_bounded
)
str
<<
"+inf)"
;
else
str
<<
apply_visitor
(
FieldVisitorToString
(),
right
)
<<
(
right_included
?
']'
:
')'
);
return
str
.
str
();
}
};
class
ASTSet
;
/** Условие на индекс.
*
* Состоит из условий на принадлежность ключа всевозможным диапазонам или множествам,
* а также логических связок AND/OR/NOT над этими условиями.
*
* Составляет reverse polish notation от этих условий
* и умеет вычислять (интерпретировать) её выполнимость над диапазонами ключа.
*/
class
PKCondition
{
public:
/// Не учитывает секцию SAMPLE. all_columns - набор всех столбцов таблицы.
PKCondition
(
ASTPtr
query
,
const
Context
&
context
,
const
NamesAndTypesList
&
all_columns
,
const
SortDescription
&
sort_descr
);
/// Выполнимо ли условие в диапазоне ключей.
/// left_pk и right_pk должны содержать все поля из sort_descr в соответствующем порядке.
bool
mayBeTrueInRange
(
const
Field
*
left_pk
,
const
Field
*
right_pk
);
/// Выполнимо ли условие в полубесконечном (не ограниченном справа) диапазоне ключей.
/// left_pk должен содержать все поля из sort_descr в соответствующем порядке.
bool
mayBeTrueAfter
(
const
Field
*
left_pk
);
bool
alwaysTrue
()
{
return
rpn
.
size
()
==
1
&&
rpn
[
0
].
function
==
RPNElement
::
FUNCTION_UNKNOWN
;
}
/// Проверяет, что индекс не может быть использован.
bool
alwaysUnknown
();
/// Наложить дополнительное условие: значение в столбце column должно быть в диапазоне range.
/// Возвращает, есть ли такой столбец в первичном ключе.
bool
addCondition
(
const
String
&
column
,
const
Range
&
range
);
String
toString
();
private:
/// Выражение хранится в виде обратной польской строки (Reverse Polish Notation).
...
...
@@ -303,37 +311,37 @@ private:
FUNCTION_AND
,
FUNCTION_OR
,
};
RPNElement
()
{}
RPNElement
(
Function
function_
)
:
function
(
function_
)
{}
RPNElement
(
Function
function_
,
size_t
key_column_
)
:
function
(
function_
),
key_column
(
key_column_
)
{}
RPNElement
(
Function
function_
,
size_t
key_column_
,
const
Range
&
range_
)
:
function
(
function_
),
range
(
range_
),
key_column
(
key_column_
)
{}
String
toString
();
Function
function
;
/// Для FUNCTION_IN_RANGE и FUNCTION_NOT_IN_RANGE.
Range
range
;
size_t
key_column
;
/// Для FUNCTION_IN_SET
ASTPtr
in_function
;
ASTSet
*
inFunctionToSet
();
};
typedef
std
::
vector
<
RPNElement
>
RPN
;
typedef
std
::
map
<
String
,
size_t
>
ColumnIndices
;
bool
mayBeTrueInRange
(
const
Field
*
left_pk
,
const
Field
*
right_pk
,
bool
right_bounded
);
void
traverseAST
(
ASTPtr
&
node
,
Block
&
block_with_constants
);
bool
atomFromAST
(
ASTPtr
&
node
,
Block
&
block_with_constants
,
RPNElement
&
out
);
bool
operatorFromAST
(
ASTFunction
*
func
,
RPNElement
&
out
);
RPN
rpn
;
SortDescription
sort_descr
;
ColumnIndices
pk_columns
;
};
...
...
dbms/src/Storages/MergeTree/MergeTreeDataSelectExecutor.cpp
浏览文件 @
cfc5b313
...
...
@@ -83,7 +83,7 @@ BlockInputStreams MergeTreeDataSelectExecutor::read(
PKCondition
key_condition
(
query
,
context
,
data
.
getColumnsList
(),
data
.
getSortDescription
());
PKCondition
date_condition
(
query
,
context
,
data
.
getColumnsList
(),
SortDescription
(
1
,
SortColumnDescription
(
data
.
date_column_name
,
1
)));
if
(
settings
.
force_index_by_date
&&
date_condition
.
always
True
())
if
(
settings
.
force_index_by_date
&&
date_condition
.
always
Unknown
())
throw
Exception
(
"Index by date is not used and setting 'force_index_by_date' is set."
,
ErrorCodes
::
INDEX_NOT_USED
);
/// Выберем куски, в которых могут быть данные, удовлетворяющие date_condition, и которые подходят под условие на _part.
...
...
@@ -556,7 +556,7 @@ MarkRanges MergeTreeDataSelectExecutor::markRangesFromPkRange(
size_t
marks_count
=
index
.
size
()
/
key_size
;
/// Если индекс не используется.
if
(
key_condition
.
always
True
())
if
(
key_condition
.
always
Unknown
())
{
res
.
push_back
(
MarkRange
(
0
,
marks_count
));
}
...
...
dbms/src/Storages/MergeTree/PKCondition.cpp
浏览文件 @
cfc5b313
...
...
@@ -267,7 +267,7 @@ bool PKCondition::mayBeTrueInRange(const Field * left_pk, const Field * right_pk
RPNElement
&
element
=
rpn
[
i
];
if
(
element
.
function
==
RPNElement
::
FUNCTION_UNKNOWN
)
{
rpn_stack
.
push_back
(
BoolMask
(
true
,
true
)
);
rpn_stack
.
emplace_back
(
true
,
true
);
}
else
if
(
element
.
function
==
RPNElement
::
FUNCTION_NOT_IN_RANGE
||
element
.
function
==
RPNElement
::
FUNCTION_IN_RANGE
)
{
...
...
@@ -275,7 +275,7 @@ bool PKCondition::mayBeTrueInRange(const Field * left_pk, const Field * right_pk
bool
intersects
=
element
.
range
.
intersectsRange
(
key_range
);
bool
contains
=
element
.
range
.
containsRange
(
key_range
);
rpn_stack
.
push_back
(
BoolMask
(
intersects
,
!
contains
)
);
rpn_stack
.
emplace_back
(
intersects
,
!
contains
);
if
(
element
.
function
==
RPNElement
::
FUNCTION_NOT_IN_RANGE
)
rpn_stack
.
back
()
=
!
rpn_stack
.
back
();
}
...
...
@@ -294,7 +294,7 @@ bool PKCondition::mayBeTrueInRange(const Field * left_pk, const Field * right_pk
}
else
{
throw
DB
::
Exception
(
"Set for IN is not created yet!"
);
throw
DB
::
Exception
(
"Set for IN is not created yet!"
,
ErrorCodes
::
LOGICAL_ERROR
);
}
}
else
if
(
element
.
function
==
RPNElement
::
FUNCTION_NOT
)
...
...
@@ -303,16 +303,16 @@ bool PKCondition::mayBeTrueInRange(const Field * left_pk, const Field * right_pk
}
else
if
(
element
.
function
==
RPNElement
::
FUNCTION_AND
)
{
BoolMask
arg1
=
rpn_stack
.
back
();
auto
arg1
=
rpn_stack
.
back
();
rpn_stack
.
pop_back
();
BoolMask
arg2
=
rpn_stack
.
back
();
auto
arg2
=
rpn_stack
.
back
();
rpn_stack
.
back
()
=
arg1
&
arg2
;
}
else
if
(
element
.
function
==
RPNElement
::
FUNCTION_OR
)
{
BoolMask
arg1
=
rpn_stack
.
back
();
auto
arg1
=
rpn_stack
.
back
();
rpn_stack
.
pop_back
();
BoolMask
arg2
=
rpn_stack
.
back
();
auto
arg2
=
rpn_stack
.
back
();
rpn_stack
.
back
()
=
arg1
|
arg2
;
}
else
...
...
@@ -374,4 +374,50 @@ String PKCondition::RPNElement::toString()
return
"ERROR"
;
}
}
bool
PKCondition
::
alwaysUnknown
()
{
std
::
vector
<
UInt8
>
rpn_stack
;
for
(
size_t
i
=
0
;
i
<
rpn
.
size
();
++
i
)
{
RPNElement
&
element
=
rpn
[
i
];
if
(
element
.
function
==
RPNElement
::
FUNCTION_UNKNOWN
)
{
rpn_stack
.
push_back
(
true
);
}
else
if
(
element
.
function
==
RPNElement
::
FUNCTION_NOT_IN_RANGE
||
element
.
function
==
RPNElement
::
FUNCTION_IN_RANGE
||
element
.
function
==
RPNElement
::
FUNCTION_IN_SET
||
element
.
function
==
RPNElement
::
FUNCTION_NOT_IN_SET
)
{
rpn_stack
.
push_back
(
false
);
}
else
if
(
element
.
function
==
RPNElement
::
FUNCTION_NOT
)
{
}
else
if
(
element
.
function
==
RPNElement
::
FUNCTION_AND
)
{
auto
arg1
=
rpn_stack
.
back
();
rpn_stack
.
pop_back
();
auto
arg2
=
rpn_stack
.
back
();
rpn_stack
.
back
()
=
arg1
&
arg2
;
}
else
if
(
element
.
function
==
RPNElement
::
FUNCTION_OR
)
{
auto
arg1
=
rpn_stack
.
back
();
rpn_stack
.
pop_back
();
auto
arg2
=
rpn_stack
.
back
();
rpn_stack
.
back
()
=
arg1
|
arg2
;
}
else
throw
Exception
(
"Unexpected function type in PKCondition::RPNElement"
,
ErrorCodes
::
LOGICAL_ERROR
);
}
return
rpn_stack
[
0
];
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录