Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
9ebce112
提交
9ebce112
authored
11月 08, 2015
作者:
S.Vladykin
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Batched join now getting initialized in Select.prepare() + query plan prints batched join info
上级
83f9141d
隐藏空白字符变更
内嵌
并排
正在显示
5 个修改的文件
包含
152 行增加
和
69 行删除
+152
-69
Select.java
h2/src/main/org/h2/command/dml/Select.java
+6
-1
IndexLookupBatch.java
h2/src/main/org/h2/index/IndexLookupBatch.java
+7
-1
JoinBatch.java
h2/src/main/org/h2/table/JoinBatch.java
+79
-45
TableFilter.java
h2/src/main/org/h2/table/TableFilter.java
+55
-22
TestTableEngines.java
h2/src/test/org/h2/test/db/TestTableEngines.java
+5
-0
没有找到文件。
h2/src/main/org/h2/command/dml/Select.java
浏览文件 @
9ebce112
...
...
@@ -9,7 +9,6 @@ import java.util.ArrayList;
import
java.util.Arrays
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
org.h2.api.ErrorCode
;
import
org.h2.api.Trigger
;
import
org.h2.command.CommandInterface
;
...
...
@@ -36,6 +35,7 @@ import org.h2.result.SortOrder;
import
org.h2.table.Column
;
import
org.h2.table.ColumnResolver
;
import
org.h2.table.IndexColumn
;
import
org.h2.table.JoinBatch
;
import
org.h2.table.Table
;
import
org.h2.table.TableFilter
;
import
org.h2.util.New
;
...
...
@@ -942,9 +942,14 @@ public class Select extends Query {
}
expressionArray
=
new
Expression
[
expressions
.
size
()];
expressions
.
toArray
(
expressionArray
);
topTableFilter
.
prepareBatch
(
0
);
isPrepared
=
true
;
}
public
JoinBatch
getJoinBatch
()
{
return
getTopTableFilter
().
getJoinBatch
();
}
@Override
public
double
getCost
()
{
return
cost
;
...
...
h2/src/main/org/h2/index/IndexLookupBatch.java
浏览文件 @
9ebce112
...
...
@@ -15,7 +15,8 @@ import org.h2.result.SearchRow;
* method {@link #isBatchFull()}} will return {@code true} or there are no more
* search rows to add. Then method {@link #find()} will be called to execute batched lookup.
* Note that a single instance of {@link IndexLookupBatch} can be reused for multiple
* sequential batched lookups.
* sequential batched lookups, moreover it can be reused for multiple queries for
* the same prepared statement.
*
* @see Index#createLookupBatch(org.h2.table.TableFilter)
* @author Sergi Vladykin
...
...
@@ -47,4 +48,9 @@ public interface IndexLookupBatch {
* @return List of future cursors for collected search rows.
*/
List
<
Future
<
Cursor
>>
find
();
/**
* Reset this batch to clear state. This method will be called before each query execution.
*/
void
reset
();
}
h2/src/main/org/h2/table/JoinBatch.java
浏览文件 @
9ebce112
...
...
@@ -28,65 +28,93 @@ import org.h2.value.ValueLong;
* @author Sergi Vladykin
*/
public
final
class
JoinBatch
{
private
static
final
Cursor
EMPTY_CURSOR
=
new
Cursor
()
{
@Override
public
boolean
previous
()
{
return
false
;
}
@Override
public
boolean
next
()
{
return
false
;
}
@Override
public
SearchRow
getSearchRow
()
{
return
null
;
}
@Override
public
Row
get
()
{
return
null
;
}
@Override
public
String
toString
()
{
return
"EMPTY_CURSOR"
;
}
};
private
int
filtersCount
;
private
JoinFilter
[]
filters
;
private
JoinFilter
top
;
private
boolean
started
;
private
JoinRow
current
;
private
boolean
found
;
/**
* This filter joined after this batched join and can be used normally.
*/
private
final
TableFilter
additionalFilter
;
/**
* @param filtersCount number of filters participating in this batched join
* @param additionalFilter table filter after this batched join.
*/
public
JoinBatch
(
TableFilter
additionalFilter
)
{
public
JoinBatch
(
int
filtersCount
,
TableFilter
additionalFilter
)
{
if
(
filtersCount
>
32
)
{
// This is because we store state in a 64 bit field, 2 bits per joined table.
throw
DbException
.
getUnsupportedException
(
"Too many tables in join (at most 32 supported)."
);
}
filters
=
new
JoinFilter
[
filtersCount
];
this
.
additionalFilter
=
additionalFilter
;
}
/**
* @param joinFilterId joined table filter id
* @return {@code true} if index really supports batching in this query
*/
public
boolean
isBatchedIndex
(
int
joinFilterId
)
{
return
filters
[
joinFilterId
].
isBatched
();
}
/**
* Reset state of this batch.
*/
public
void
reset
()
{
current
=
null
;
started
=
false
;
found
=
false
;
for
(
JoinFilter
jf
:
filters
)
{
jf
.
reset
();
}
if
(
additionalFilter
!=
null
)
{
additionalFilter
.
reset
();
}
}
/**
* @param filter table filter
* @param lookupBatch lookup batch
*/
public
void
register
(
TableFilter
filter
,
IndexLookupBatch
lookupBatch
)
{
assert
filter
!=
null
;
filtersCount
++;
top
=
new
JoinFilter
(
lookupBatch
,
filter
,
top
);
filters
[
top
.
id
]
=
top
;
}
/**
* @param filterId table filter id
* @param column column
...
...
@@ -108,21 +136,9 @@ public final class JoinBatch {
}
private
void
start
()
{
if
(
filtersCount
>
32
)
{
// This is because we store state in a 64 bit field, 2 bits per joined table.
throw
DbException
.
getUnsupportedException
(
"Too many tables in join (at most 32 supported)."
);
}
// fill filters
filters
=
new
JoinFilter
[
filtersCount
];
JoinFilter
jf
=
top
;
for
(
int
i
=
0
;
i
<
filtersCount
;
i
++)
{
jf
.
id
=
jf
.
filter
.
joinFilterId
=
i
;
filters
[
i
]
=
jf
;
jf
=
jf
.
join
;
}
// TODO if filters[0].isBatched() then use batching instead of top.filter.getIndexCursor()
// initialize current row
current
=
new
JoinRow
(
new
Object
[
filters
Count
]);
current
=
new
JoinRow
(
new
Object
[
filters
.
length
]);
current
.
updateRow
(
top
.
id
,
top
.
filter
.
getIndexCursor
(),
JoinRow
.
S_NULL
,
JoinRow
.
S_CURSOR
);
// initialize top cursor
...
...
@@ -188,7 +204,7 @@ public final class JoinBatch {
}
current
.
prev
=
null
;
final
int
lastJfId
=
filters
Count
-
1
;
final
int
lastJfId
=
filters
.
length
-
1
;
int
jfId
=
lastJfId
;
while
(
current
.
row
(
jfId
)
==
null
)
{
...
...
@@ -325,17 +341,28 @@ public final class JoinBatch {
private
static
final
class
JoinFilter
{
private
final
TableFilter
filter
;
private
final
JoinFilter
join
;
private
int
id
;
private
final
int
id
;
private
final
boolean
fakeBatch
;
private
final
IndexLookupBatch
lookupBatch
;
private
JoinFilter
(
IndexLookupBatch
lookupBatch
,
TableFilter
filter
,
JoinFilter
join
)
{
this
.
filter
=
filter
;
this
.
id
=
filter
.
getJoinFilterId
();
this
.
join
=
join
;
this
.
lookupBatch
=
lookupBatch
!=
null
?
lookupBatch
:
new
FakeLookupBatch
(
filter
);
fakeBatch
=
lookupBatch
==
null
;
this
.
lookupBatch
=
fakeBatch
?
new
FakeLookupBatch
(
filter
)
:
lookupBatch
;
}
public
Row
getNullRow
()
{
private
boolean
isBatched
()
{
return
!
fakeBatch
;
}
private
void
reset
()
{
lookupBatch
.
reset
();
}
private
Row
getNullRow
()
{
return
filter
.
getTable
().
getNullRow
();
}
...
...
@@ -353,7 +380,7 @@ public final class JoinBatch {
return
filterOk
&&
(
ignoreJoinCondition
||
joinOk
);
}
private
boolean
collectSearchRows
()
{
assert
!
isBatchFull
();
IndexCursor
c
=
filter
.
getIndexCursor
();
...
...
@@ -364,7 +391,7 @@ public final class JoinBatch {
lookupBatch
.
addSearchRows
(
c
.
getStart
(),
c
.
getEnd
());
return
true
;
}
private
JoinRow
find
(
JoinRow
current
)
{
assert
current
!=
null
;
...
...
@@ -403,13 +430,13 @@ public final class JoinBatch {
// the last updated row
return
current
;
}
@Override
public
String
toString
()
{
return
"JoinFilter->"
+
filter
;
}
}
/**
* Linked row in batched join.
*/
...
...
@@ -504,7 +531,7 @@ public final class JoinBatch {
}
row
=
null
;
}
/**
* Copy this JoinRow behind itself in linked list of all in progress rows.
*
...
...
@@ -514,24 +541,24 @@ public final class JoinBatch {
private
JoinRow
copyBehind
(
int
jfId
)
{
assert
isCursor
(
jfId
);
assert
jfId
+
1
==
row
.
length
||
row
[
jfId
+
1
]
==
null
;
Object
[]
r
=
new
Object
[
row
.
length
];
if
(
jfId
!=
0
)
{
System
.
arraycopy
(
row
,
0
,
r
,
0
,
jfId
);
}
JoinRow
copy
=
new
JoinRow
(
r
);
copy
.
state
=
state
;
if
(
prev
!=
null
)
{
copy
.
prev
=
prev
;
prev
.
next
=
copy
;
}
prev
=
copy
;
copy
.
next
=
this
;
return
copy
;
}
@Override
public
String
toString
()
{
return
"JoinRow->"
+
Arrays
.
toString
(
row
);
...
...
@@ -559,6 +586,13 @@ public final class JoinBatch {
this
.
filter
=
filter
;
}
@Override
public
void
reset
()
{
full
=
false
;
first
=
last
=
null
;
result
.
set
(
0
,
null
);
}
@Override
public
void
addSearchRows
(
SearchRow
first
,
SearchRow
last
)
{
assert
!
full
;
...
...
h2/src/main/org/h2/table/TableFilter.java
浏览文件 @
9ebce112
...
...
@@ -60,7 +60,7 @@ public class TableFilter implements ColumnResolver {
* Batched join support.
*/
private
JoinBatch
joinBatch
;
int
joinFilterId
=
-
1
;
private
int
joinFilterId
=
-
1
;
/**
* Indicates that this filter is used in the plan.
...
...
@@ -308,52 +308,77 @@ public class TableFilter implements ColumnResolver {
* Start the query. This will reset the scan counts.
*
* @param s the session
* @return join batch if query runs over index which supports batched lookups, null otherwise
*/
public
JoinBatch
startQuery
(
Session
s
)
{
joinBatch
=
null
;
joinFilterId
=
-
1
;
public
void
startQuery
(
Session
s
)
{
this
.
session
=
s
;
scanCount
=
0
;
if
(
nestedJoin
!=
null
)
{
nestedJoin
.
startQuery
(
s
);
}
if
(
join
!=
null
)
{
join
.
startQuery
(
s
);
}
}
/**
* Reset to the current position.
*/
public
void
reset
()
{
if
(
joinBatch
!=
null
&&
joinFilterId
==
0
)
{
// reset join batch only on top table filter
joinBatch
.
reset
();
return
;
}
if
(
nestedJoin
!=
null
)
{
nestedJoin
.
reset
();
}
if
(
join
!=
null
)
{
join
.
reset
();
}
state
=
BEFORE_FIRST
;
foundOne
=
false
;
}
/**
* Attempt to initialize batched join.
*
* @param id join filter id (index of this table filter in join list)
* @return join batch if query runs over index which supports batched lookups, {@code null} otherwise
*/
public
JoinBatch
prepareBatch
(
int
id
)
{
JoinBatch
batch
=
null
;
if
(
join
!=
null
)
{
batch
=
join
.
startQuery
(
s
);
batch
=
join
.
prepareBatch
(
id
+
1
);
}
IndexLookupBatch
lookupBatch
=
null
;
if
(
batch
==
null
&&
select
!=
null
&&
select
.
getTopTableFilter
()
!=
this
)
{
if
(
batch
==
null
&&
select
!=
null
&&
id
!=
0
)
{
// TODO session.getSubQueryInfo() instead of id != 0 + use upper level sub-query info
lookupBatch
=
index
.
createLookupBatch
(
this
);
if
(
lookupBatch
!=
null
)
{
batch
=
new
JoinBatch
(
join
);
batch
=
new
JoinBatch
(
id
+
1
,
join
);
}
}
if
(
batch
!=
null
)
{
if
(
nestedJoin
!=
null
)
{
throw
DbException
.
getUnsupportedException
(
"nested join with batched index"
);
}
if
(
lookupBatch
==
null
)
{
if
(
lookupBatch
==
null
&&
id
!=
0
)
{
// TODO session.getSubQueryInfo() instead of id != 0 + use upper level sub-query info
lookupBatch
=
index
.
createLookupBatch
(
this
);
}
joinBatch
=
batch
;
joinFilterId
=
id
;
batch
.
register
(
this
,
lookupBatch
);
}
return
batch
;
}
/**
* Reset to the current position.
*/
public
void
reset
()
{
if
(
nestedJoin
!=
null
)
{
nestedJoin
.
reset
();
}
if
(
join
!=
null
)
{
join
.
reset
();
}
state
=
BEFORE_FIRST
;
foundOne
=
false
;
public
int
getJoinFilterId
()
{
return
joinFilterId
;
}
public
JoinBatch
getJoinBatch
()
{
return
joinBatch
;
}
/**
...
...
@@ -363,7 +388,7 @@ public class TableFilter implements ColumnResolver {
*/
public
boolean
next
()
{
if
(
joinBatch
!=
null
)
{
// will happen only on topTableFilter since j
batch.next
does not call join.next()
// will happen only on topTableFilter since j
oinBatch.next()
does not call join.next()
return
joinBatch
.
next
();
}
if
(
state
==
AFTER_LAST
)
{
...
...
@@ -722,6 +747,14 @@ public class TableFilter implements ColumnResolver {
if
(
index
!=
null
)
{
buff
.
append
(
'\n'
);
StatementBuilder
planBuff
=
new
StatementBuilder
();
if
(
joinBatch
!=
null
)
{
if
(
joinBatch
.
isBatchedIndex
(
joinFilterId
))
{
planBuff
.
append
(
"batched:true "
);
}
else
if
(
joinFilterId
!=
0
)
{
// top table filter does not need to fake batching, it works as usual in this case
planBuff
.
append
(
"batched:fake "
);
}
}
planBuff
.
append
(
index
.
getPlanSQL
());
if
(
indexConditions
.
size
()
>
0
)
{
planBuff
.
append
(
": "
);
...
...
h2/src/test/org/h2/test/db/TestTableEngines.java
浏览文件 @
9ebce112
...
...
@@ -1118,6 +1118,11 @@ public class TestTableEngines extends TestBase {
searchRows
.
add
(
first
);
searchRows
.
add
(
last
);
}
@Override
public
void
reset
()
{
searchRows
.
clear
();
}
};
}
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论