Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
68032a31
提交
68032a31
authored
11月 24, 2015
作者:
S.Vladykin
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
added more tests
上级
4232718e
显示空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
136 行增加
和
46 行删除
+136
-46
JoinBatch.java
h2/src/main/org/h2/table/JoinBatch.java
+36
-26
TableFilter.java
h2/src/main/org/h2/table/TableFilter.java
+21
-17
TestTableEngines.java
h2/src/test/org/h2/test/db/TestTableEngines.java
+79
-3
没有找到文件。
h2/src/main/org/h2/table/JoinBatch.java
浏览文件 @
68032a31
...
...
@@ -374,14 +374,13 @@ public final class JoinBatch {
*/
public
static
IndexLookupBatch
createViewIndexLookupBatch
(
ViewIndex
viewIndex
)
{
Query
query
=
viewIndex
.
getQuery
();
query
.
prepareJoinBatch
();
if
(
query
.
isUnion
())
{
ViewIndexLookupBatchUnion
unionBatch
=
new
ViewIndexLookupBatchUnion
(
viewIndex
);
return
unionBatch
.
hasBatchedQueries
()
?
unionBatch
:
null
;
return
unionBatch
.
initialize
()
?
unionBatch
:
null
;
}
JoinBatch
jb
=
((
Select
)
query
).
getJoinBatch
();
if
(
jb
==
null
)
{
// our sub-query is not batched
, will run usual wa
y
if
(
jb
==
null
||
jb
.
getLookupBatch
(
0
)
==
null
)
{
// our sub-query is not batched
or is top batched sub-quer
y
return
null
;
}
assert
!
jb
.
batchedSubQuery
;
...
...
@@ -389,6 +388,16 @@ public final class JoinBatch {
return
jb
.
viewIndexLookupBatch
(
viewIndex
);
}
/**
* Create fake index lookup batch for non-batched table filter.
*
* @param filter the table filter
* @return fake index lookup batch
*/
public
static
IndexLookupBatch
createFakeIndexLookupBatch
(
TableFilter
filter
)
{
return
new
FakeLookupBatch
(
filter
);
}
@Override
public
String
toString
()
{
return
"JoinBatch->\nprev->"
+
(
current
==
null
?
null
:
current
.
prev
)
+
...
...
@@ -410,10 +419,8 @@ public final class JoinBatch {
this
.
filter
=
filter
;
this
.
id
=
filter
.
getJoinFilterId
();
this
.
join
=
join
;
if
(
lookupBatch
==
null
&&
id
!=
0
)
{
lookupBatch
=
new
FakeLookupBatch
(
filter
);
}
this
.
lookupBatch
=
lookupBatch
;
assert
lookupBatch
!=
null
||
id
==
0
;
}
private
void
reset
()
{
...
...
@@ -913,24 +920,27 @@ public final class JoinBatch {
protected
ViewIndexLookupBatchUnion
(
ViewIndex
viewIndex
)
{
super
(
viewIndex
);
collectJoinBatches
(
viewIndex
.
getQuery
());
}
private
boolean
hasBatchedQueries
()
{
return
joinBatches
!=
null
;
private
boolean
initialize
()
{
return
collectJoinBatches
(
viewIndex
.
getQuery
())
&&
joinBatches
!=
null
;
}
private
void
collectJoinBatches
(
Query
query
)
{
private
boolean
collectJoinBatches
(
Query
query
)
{
if
(
query
.
isUnion
())
{
SelectUnion
union
=
(
SelectUnion
)
query
;
collectJoinBatches
(
union
.
getLeft
());
return
collectJoinBatches
(
union
.
getLeft
())
&&
collectJoinBatches
(
union
.
getRight
());
}
else
{
}
Select
select
=
(
Select
)
query
;
JoinBatch
jb
=
select
.
getJoinBatch
();
if
(
jb
==
null
)
{
onlyBatchedQueries
=
false
;
}
else
{
if
(
jb
.
getLookupBatch
(
0
)
==
null
)
{
// we are top sub-query
return
false
;
}
assert
!
jb
.
batchedSubQuery
;
jb
.
batchedSubQuery
=
true
;
if
(
joinBatches
==
null
)
{
...
...
@@ -940,7 +950,7 @@ public final class JoinBatch {
filters
.
add
(
jb
.
filters
[
0
]);
joinBatches
.
add
(
jb
);
}
}
return
true
;
}
@Override
...
...
h2/src/main/org/h2/table/TableFilter.java
浏览文件 @
68032a31
...
...
@@ -20,6 +20,7 @@ import org.h2.index.Index;
import
org.h2.index.IndexLookupBatch
;
import
org.h2.index.IndexCondition
;
import
org.h2.index.IndexCursor
;
import
org.h2.index.ViewIndex
;
import
org.h2.message.DbException
;
import
org.h2.result.Row
;
import
org.h2.result.SearchRow
;
...
...
@@ -368,6 +369,14 @@ public class TableFilter implements ColumnResolver {
joinBatch
=
null
;
joinFilterId
=
-
1
;
IndexLookupBatch
lookupBatch
=
null
;
if
(
getTable
().
isView
())
{
session
.
pushSubQueryInfo
(
masks
,
filters
,
filter
,
select
.
getSortOrder
());
try
{
((
ViewIndex
)
index
).
getQuery
().
prepareJoinBatch
();
}
finally
{
session
.
popSubQueryInfo
();
}
}
// For globally top table filter we don't need to create lookup batch, because
// currently it will not be used (this will be shown in ViewIndex.getPlanSQL()). Probably
// later on it will make sense to create it to better support X IN (...) conditions,
...
...
@@ -376,7 +385,7 @@ public class TableFilter implements ColumnResolver {
// in turn is not top in outer query, thus we need to enable batching here to allow
// outer query run batched join against this sub-query.
if
(
jb
==
null
&&
select
!=
null
&&
!
isAlwaysTopTableFilter
(
filter
))
{
lookupBatch
=
createLookupBatch
(
filters
,
filter
);
lookupBatch
=
index
.
createLookupBatch
(
this
);
if
(
lookupBatch
!=
null
)
{
jb
=
new
JoinBatch
(
filter
+
1
,
join
);
}
...
...
@@ -387,26 +396,21 @@ public class TableFilter implements ColumnResolver {
}
joinBatch
=
jb
;
joinFilterId
=
filter
;
if
(
lookupBatch
==
null
&&
!
isAlwaysTopTableFilter
(
filter
))
{
if
(
lookupBatch
==
null
)
{
boolean
notTop
=
!
isAlwaysTopTableFilter
(
filter
);
if
(
notTop
||
getTable
().
isView
())
{
// createLookupBatch will be called at most once because jb can be
// created only if lookupBatch is already not null from the call above.
lookupBatch
=
createLookupBatch
(
filters
,
filter
);
lookupBatch
=
index
.
createLookupBatch
(
this
);
if
(
lookupBatch
==
null
&&
notTop
)
{
// the index does not support lookup batching, need to fake it because we are not top
lookupBatch
=
JoinBatch
.
createFakeIndexLookupBatch
(
this
);
}
jb
.
register
(
this
,
lookupBatch
);
}
return
jb
;
}
private
IndexLookupBatch
createLookupBatch
(
TableFilter
[]
filters
,
int
filter
)
{
if
(
getTable
().
isView
())
{
session
.
pushSubQueryInfo
(
masks
,
filters
,
filter
,
select
.
getSortOrder
());
try
{
return
index
.
createLookupBatch
(
this
);
}
finally
{
session
.
popSubQueryInfo
();
}
jb
.
register
(
this
,
lookupBatch
);
}
return
index
.
createLookupBatch
(
this
)
;
return
jb
;
}
public
int
getJoinFilterId
()
{
...
...
h2/src/test/org/h2/test/db/TestTableEngines.java
浏览文件 @
68032a31
...
...
@@ -489,15 +489,15 @@ public class TestTableEngines extends TestBase {
stat
.
execute
(
"CREATE INDEX T_IDX_B ON t(b)"
);
setBatchSize
(
t
,
3
);
for
(
int
i
=
0
;
i
<
20
;
i
++)
{
stat
.
execute
(
"insert into t values ("
+
i
+
","
+
i
+
")"
);
stat
.
execute
(
"insert into t values ("
+
i
+
","
+
(
i
+
10
)
+
")"
);
}
stat
.
execute
(
"CREATE TABLE u (a int, b int) ENGINE "
+
engine
);
TreeSetTable
u
=
TreeSetIndexTableEngine
.
created
;
stat
.
execute
(
"CREATE INDEX U_IDX_A ON u(a)"
);
stat
.
execute
(
"CREATE INDEX U_IDX_B ON u(b)"
);
setBatchSize
(
u
,
0
);
for
(
int
i
=
0
;
i
<
20
;
i
++)
{
stat
.
execute
(
"insert into u values ("
+
i
+
","
+
i
+
")"
);
for
(
int
i
=
10
;
i
<
25
;
i
++)
{
stat
.
execute
(
"insert into u values ("
+
i
+
","
+
(
i
-
15
)
+
")"
);
}
checkPlan
(
stat
,
"SELECT 1 FROM PUBLIC.T T1 /* PUBLIC.\"scan\" */ "
...
...
@@ -521,11 +521,87 @@ public class TestTableEngines extends TestBase {
+
"INNER JOIN ( SELECT A FROM PUBLIC.T ) Z "
+
"/* batched:view SELECT A FROM PUBLIC.T /++ batched:test PUBLIC.T_IDX_A: A IS ?1 ++/ "
+
"WHERE A IS ?1: A = T.B */ ON 1=1 WHERE Z.A = T.B"
);
checkPlan
(
stat
,
"SELECT 1 FROM PUBLIC.T /* PUBLIC.\"scan\" */ "
+
"INNER JOIN ( ((SELECT A FROM PUBLIC.T) UNION ALL (SELECT B FROM PUBLIC.U)) "
+
"UNION ALL (SELECT B FROM PUBLIC.T) ) Z /* batched:view "
+
"((SELECT A FROM PUBLIC.T /++ batched:test PUBLIC.T_IDX_A: A IS ?1 ++/ WHERE A IS ?1) "
+
"UNION ALL "
+
"(SELECT B FROM PUBLIC.U /++ PUBLIC.U_IDX_B: B IS ?1 ++/ WHERE B IS ?1)) "
+
"UNION ALL "
+
"(SELECT B FROM PUBLIC.T /++ batched:test PUBLIC.T_IDX_B: B IS ?1 ++/ WHERE B IS ?1)"
+
": A = T.A */ ON 1=1 WHERE Z.A = T.A"
);
checkPlan
(
stat
,
"SELECT 1 FROM PUBLIC.T /* PUBLIC.\"scan\" */ "
+
"INNER JOIN ( SELECT U.A FROM PUBLIC.U INNER JOIN PUBLIC.T ON 1=1 WHERE U.B = T.B ) Z "
+
"/* batched:view SELECT U.A FROM PUBLIC.U /++ batched:fake PUBLIC.U_IDX_A: A IS ?1 ++/ "
+
"/++ WHERE U.A IS ?1 ++/ INNER JOIN PUBLIC.T /++ batched:test PUBLIC.T_IDX_B: B = U.B ++/ "
+
"ON 1=1 WHERE (U.A IS ?1) AND (U.B = T.B): A = T.A */ ON 1=1 WHERE Z.A = T.A"
);
checkPlan
(
stat
,
"SELECT 1 FROM PUBLIC.T /* PUBLIC.\"scan\" */ "
+
"INNER JOIN ( SELECT A FROM PUBLIC.U ) Z /* SELECT A FROM PUBLIC.U "
+
"/++ PUBLIC.U_IDX_A: A IS ?1 ++/ WHERE A IS ?1: A = T.A */ ON 1=1 WHERE T.A = Z.A"
);
checkPlan
(
stat
,
"SELECT 1 FROM "
+
"( SELECT U.A FROM PUBLIC.U INNER JOIN PUBLIC.T ON 1=1 WHERE U.B = T.B ) Z "
+
"/* SELECT U.A FROM PUBLIC.U /++ PUBLIC.\"scan\" ++/ "
+
"INNER JOIN PUBLIC.T /++ batched:test PUBLIC.T_IDX_B: B = U.B ++/ "
+
"ON 1=1 WHERE U.B = T.B */ "
+
"INNER JOIN PUBLIC.T /* batched:test PUBLIC.T_IDX_A: A = Z.A */ ON 1=1 WHERE T.A = Z.A"
);
checkPlan
(
stat
,
"SELECT 1 FROM "
+
"( SELECT U.A FROM PUBLIC.T INNER JOIN PUBLIC.U ON 1=1 WHERE T.B = U.B ) Z "
+
"/* SELECT U.A FROM PUBLIC.T /++ PUBLIC.\"scan\" ++/ "
+
"INNER JOIN PUBLIC.U /++ PUBLIC.U_IDX_B: B = T.B ++/ "
+
"ON 1=1 WHERE T.B = U.B */ INNER JOIN PUBLIC.T /* batched:test PUBLIC.T_IDX_A: A = Z.A */ "
+
"ON 1=1 WHERE Z.A = T.A"
);
checkPlan
(
stat
,
"SELECT 1 FROM ( (SELECT A FROM PUBLIC.T) UNION (SELECT A FROM PUBLIC.U) ) Z "
+
"/* (SELECT A FROM PUBLIC.T /++ PUBLIC.\"scan\" ++/) "
+
"UNION "
+
"(SELECT A FROM PUBLIC.U /++ PUBLIC.\"scan\" ++/) */ "
+
"INNER JOIN PUBLIC.T /* batched:test PUBLIC.T_IDX_A: A = Z.A */ ON 1=1 WHERE Z.A = T.A"
);
checkPlan
(
stat
,
"SELECT 1 FROM PUBLIC.U /* PUBLIC.\"scan\" */ "
+
"INNER JOIN ( (SELECT A, B FROM PUBLIC.T) UNION (SELECT B, A FROM PUBLIC.U) ) Z "
+
"/* batched:view (SELECT A, B FROM PUBLIC.T /++ batched:test PUBLIC.T_IDX_B: B IS ?1 ++/ "
+
"WHERE B IS ?1) UNION (SELECT B, A FROM PUBLIC.U /++ PUBLIC.U_IDX_A: A IS ?1 ++/ "
+
"WHERE A IS ?1): B = U.B */ ON 1=1 /* WHERE U.B = Z.B */ "
+
"INNER JOIN PUBLIC.T /* batched:test PUBLIC.T_IDX_A: A = Z.A */ ON 1=1 "
+
"WHERE (U.B = Z.B) AND (Z.A = T.A)"
);
checkPlan
(
stat
,
"SELECT 1 FROM PUBLIC.U /* PUBLIC.\"scan\" */ "
+
"INNER JOIN ( SELECT A, B FROM PUBLIC.U ) Z "
+
"/* batched:fake SELECT A, B FROM PUBLIC.U /++ PUBLIC.U_IDX_A: A IS ?1 ++/ "
+
"WHERE A IS ?1: A = U.A */ ON 1=1 /* WHERE U.A = Z.A */ "
+
"INNER JOIN PUBLIC.T /* batched:test PUBLIC.T_IDX_B: B = Z.B */ "
+
"ON 1=1 WHERE (U.A = Z.A) AND (Z.B = T.B)"
);
// t: a = [ 0..20), b = [10..30)
// u: a = [10..25), b = [-5..10)
checkBatchedQueryResult
(
stat
,
10
,
"select t.a from t, (select t.b from u, t where u.a = t.a) z where t.b = z.b"
);
checkBatchedQueryResult
(
stat
,
5
,
"select t.a from (select t1.b from t t1, t t2 where t1.a = t2.b) z, t where t.b = z.b + 5"
);
checkBatchedQueryResult
(
stat
,
1
,
"select t.a from (select u.b from u, t t2 where u.a = t2.b) z, t where t.b = z.b + 1"
);
checkBatchedQueryResult
(
stat
,
15
,
"select t.a from (select u.b from u, t t2 where u.a = t2.b) z left join t on t.b = z.b"
);
checkBatchedQueryResult
(
stat
,
15
,
"select t.a from (select t1.b from t t1 left join t t2 on t1.a = t2.b) z, t "
+
"where t.b = z.b + 5"
);
checkBatchedQueryResult
(
stat
,
1
,
"select t.a from t,(select 5 as b from t union select 10 from u) z "
+
"where t.b = z.b"
);
checkBatchedQueryResult
(
stat
,
15
,
"select t.a from u,(select 5 as b, a from t "
+
"union select 10, a from u) z, t where t.b = z.b and z.a = u.a"
);
stat
.
execute
(
"DROP TABLE T"
);
stat
.
execute
(
"DROP TABLE U"
);
}
private
void
checkBatchedQueryResult
(
Statement
stat
,
int
size
,
String
sql
)
throws
SQLException
{
setBatchingEnabled
(
stat
,
false
);
List
<
List
<
Object
>>
expected
=
query
(
stat
,
sql
);
assertEquals
(
size
,
expected
.
size
());
setBatchingEnabled
(
stat
,
true
);
List
<
List
<
Object
>>
actual
=
query
(
stat
,
sql
);
if
(!
expected
.
equals
(
actual
))
{
fail
(
"\nexpected: "
+
expected
+
"\nactual: "
+
actual
);
}
}
private
void
doTestBatchedJoin
(
Statement
stat
,
int
...
batchSizes
)
throws
SQLException
{
ArrayList
<
TreeSetTable
>
tables
=
New
.
arrayList
(
batchSizes
.
length
);
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论