Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
58425db8
提交
58425db8
authored
9 年前
作者:
S.Vladykin
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
plan and tests
上级
233ddba8
隐藏空白字符变更
内嵌
并排
正在显示
11 个修改的文件
包含
207 行增加
和
77 行删除
+207
-77
CommandContainer.java
h2/src/main/org/h2/command/CommandContainer.java
+13
-2
AlterTableAddConstraint.java
h2/src/main/org/h2/command/ddl/AlterTableAddConstraint.java
+6
-0
Delete.java
h2/src/main/org/h2/command/dml/Delete.java
+1
-1
Explain.java
h2/src/main/org/h2/command/dml/Explain.java
+4
-0
NoOperation.java
h2/src/main/org/h2/command/dml/NoOperation.java
+0
-5
Select.java
h2/src/main/org/h2/command/dml/Select.java
+1
-3
Update.java
h2/src/main/org/h2/command/dml/Update.java
+1
-1
IndexLookupBatch.java
h2/src/main/org/h2/index/IndexLookupBatch.java
+7
-0
JoinBatch.java
h2/src/main/org/h2/table/JoinBatch.java
+46
-46
TableFilter.java
h2/src/main/org/h2/table/TableFilter.java
+22
-13
TestTableEngines.java
h2/src/test/org/h2/test/db/TestTableEngines.java
+106
-6
没有找到文件。
h2/src/main/org/h2/command/CommandContainer.java
浏览文件 @
58425db8
...
@@ -7,6 +7,7 @@ package org.h2.command;
...
@@ -7,6 +7,7 @@ package org.h2.command;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
org.h2.api.DatabaseEventListener
;
import
org.h2.api.DatabaseEventListener
;
import
org.h2.command.dml.Explain
;
import
org.h2.command.dml.Query
;
import
org.h2.command.dml.Query
;
import
org.h2.expression.Parameter
;
import
org.h2.expression.Parameter
;
import
org.h2.expression.ParameterInterface
;
import
org.h2.expression.ParameterInterface
;
...
@@ -47,8 +48,18 @@ public class CommandContainer extends Command {
...
@@ -47,8 +48,18 @@ public class CommandContainer extends Command {
@Override
@Override
public
void
prepareJoinBatch
()
{
public
void
prepareJoinBatch
()
{
if
(
session
.
isJoinBatchEnabled
()
&&
prepared
.
isQuery
())
{
if
(
session
.
isJoinBatchEnabled
())
{
((
Query
)
prepared
).
prepareJoinBatch
();
prepareJoinBatch
(
prepared
);
}
}
private
static
void
prepareJoinBatch
(
Prepared
prepared
)
{
if
(
prepared
.
isQuery
())
{
if
(
prepared
.
getType
()
==
CommandInterface
.
SELECT
)
{
((
Query
)
prepared
).
prepareJoinBatch
();
}
else
if
(
prepared
.
getType
()
==
CommandInterface
.
EXPLAIN
)
{
prepareJoinBatch
(((
Explain
)
prepared
).
getCommand
());
}
}
}
}
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/command/ddl/AlterTableAddConstraint.java
浏览文件 @
58425db8
...
@@ -294,6 +294,9 @@ public class AlterTableAddConstraint extends SchemaCommand {
...
@@ -294,6 +294,9 @@ public class AlterTableAddConstraint extends SchemaCommand {
}
}
private
static
Index
getUniqueIndex
(
Table
t
,
IndexColumn
[]
cols
)
{
private
static
Index
getUniqueIndex
(
Table
t
,
IndexColumn
[]
cols
)
{
if
(
t
.
getIndexes
()
==
null
)
{
return
null
;
}
for
(
Index
idx
:
t
.
getIndexes
())
{
for
(
Index
idx
:
t
.
getIndexes
())
{
if
(
canUseUniqueIndex
(
idx
,
t
,
cols
))
{
if
(
canUseUniqueIndex
(
idx
,
t
,
cols
))
{
return
idx
;
return
idx
;
...
@@ -303,6 +306,9 @@ public class AlterTableAddConstraint extends SchemaCommand {
...
@@ -303,6 +306,9 @@ public class AlterTableAddConstraint extends SchemaCommand {
}
}
private
static
Index
getIndex
(
Table
t
,
IndexColumn
[]
cols
,
boolean
moreColumnOk
)
{
private
static
Index
getIndex
(
Table
t
,
IndexColumn
[]
cols
,
boolean
moreColumnOk
)
{
if
(
t
.
getIndexes
()
==
null
)
{
return
null
;
}
for
(
Index
idx
:
t
.
getIndexes
())
{
for
(
Index
idx
:
t
.
getIndexes
())
{
if
(
canUseIndex
(
idx
,
t
,
cols
,
moreColumnOk
))
{
if
(
canUseIndex
(
idx
,
t
,
cols
,
moreColumnOk
))
{
return
idx
;
return
idx
;
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/command/dml/Delete.java
浏览文件 @
58425db8
...
@@ -132,7 +132,7 @@ public class Delete extends Prepared {
...
@@ -132,7 +132,7 @@ public class Delete extends Prepared {
}
}
PlanItem
item
=
tableFilter
.
getBestPlanItem
(
session
,
new
TableFilter
[]{
tableFilter
},
0
);
PlanItem
item
=
tableFilter
.
getBestPlanItem
(
session
,
new
TableFilter
[]{
tableFilter
},
0
);
tableFilter
.
setPlanItem
(
item
);
tableFilter
.
setPlanItem
(
item
);
tableFilter
.
prepare
();
tableFilter
.
prepare
(
false
);
}
}
@Override
@Override
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/command/dml/Explain.java
浏览文件 @
58425db8
...
@@ -40,6 +40,10 @@ public class Explain extends Prepared {
...
@@ -40,6 +40,10 @@ public class Explain extends Prepared {
this
.
command
=
command
;
this
.
command
=
command
;
}
}
public
Prepared
getCommand
()
{
return
command
;
}
@Override
@Override
public
void
prepare
()
{
public
void
prepare
()
{
command
.
prepare
();
command
.
prepare
();
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/command/dml/NoOperation.java
浏览文件 @
58425db8
...
@@ -24,11 +24,6 @@ public class NoOperation extends Prepared {
...
@@ -24,11 +24,6 @@ public class NoOperation extends Prepared {
return
0
;
return
0
;
}
}
@Override
public
boolean
isQuery
()
{
return
false
;
}
@Override
@Override
public
boolean
isTransactional
()
{
public
boolean
isTransactional
()
{
return
true
;
return
true
;
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/command/dml/Select.java
浏览文件 @
58425db8
...
@@ -1010,9 +1010,7 @@ public class Select extends Query {
...
@@ -1010,9 +1010,7 @@ public class Select extends Query {
setEvaluatableRecursive
(
topTableFilter
);
setEvaluatableRecursive
(
topTableFilter
);
if
(!
parse
)
{
topTableFilter
.
prepare
(
parse
);
topTableFilter
.
prepare
();
}
return
planCost
;
return
planCost
;
}
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/command/dml/Update.java
浏览文件 @
58425db8
...
@@ -189,7 +189,7 @@ public class Update extends Prepared {
...
@@ -189,7 +189,7 @@ public class Update extends Prepared {
}
}
PlanItem
item
=
tableFilter
.
getBestPlanItem
(
session
,
new
TableFilter
[]
{
tableFilter
},
0
);
PlanItem
item
=
tableFilter
.
getBestPlanItem
(
session
,
new
TableFilter
[]
{
tableFilter
},
0
);
tableFilter
.
setPlanItem
(
item
);
tableFilter
.
setPlanItem
(
item
);
tableFilter
.
prepare
();
tableFilter
.
prepare
(
false
);
}
}
@Override
@Override
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/index/IndexLookupBatch.java
浏览文件 @
58425db8
...
@@ -51,6 +51,13 @@ public interface IndexLookupBatch {
...
@@ -51,6 +51,13 @@ public interface IndexLookupBatch {
*/
*/
List
<
Future
<
Cursor
>>
find
();
List
<
Future
<
Cursor
>>
find
();
/**
* Get plan for EXPLAIN.
*
* @return plan
*/
String
getPlanSQL
();
/**
/**
* Reset this batch to clear state. This method will be called before each query execution.
* Reset this batch to clear state. This method will be called before each query execution.
*/
*/
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/table/JoinBatch.java
浏览文件 @
58425db8
...
@@ -95,16 +95,6 @@ public final class JoinBatch {
...
@@ -95,16 +95,6 @@ public final class JoinBatch {
this
.
additionalFilter
=
additionalFilter
;
this
.
additionalFilter
=
additionalFilter
;
}
}
/**
* Check if the index at the given table filter really supports batching in this query.
*
* @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
();
}
/**
/**
* Get the lookup batch for the given table filter.
* Get the lookup batch for the given table filter.
*
*
...
@@ -413,7 +403,6 @@ public final class JoinBatch {
...
@@ -413,7 +403,6 @@ public final class JoinBatch {
private
final
TableFilter
filter
;
private
final
TableFilter
filter
;
private
final
JoinFilter
join
;
private
final
JoinFilter
join
;
private
final
int
id
;
private
final
int
id
;
private
final
boolean
fakeBatch
;
private
final
IndexLookupBatch
lookupBatch
;
private
final
IndexLookupBatch
lookupBatch
;
...
@@ -421,16 +410,16 @@ public final class JoinBatch {
...
@@ -421,16 +410,16 @@ public final class JoinBatch {
this
.
filter
=
filter
;
this
.
filter
=
filter
;
this
.
id
=
filter
.
getJoinFilterId
();
this
.
id
=
filter
.
getJoinFilterId
();
this
.
join
=
join
;
this
.
join
=
join
;
fakeBatch
=
lookupBatch
==
null
;
if
(
lookupBatch
==
null
&&
id
!=
0
)
{
this
.
lookupBatch
=
fakeBatch
?
new
FakeLookupBatch
(
filter
)
:
lookupBatch
;
lookupBatch
=
new
FakeLookupBatch
(
filter
);
}
}
this
.
lookupBatch
=
lookupBatch
;
private
boolean
isBatched
()
{
return
!
fakeBatch
;
}
}
private
void
reset
()
{
private
void
reset
()
{
lookupBatch
.
reset
();
if
(
lookupBatch
!=
null
)
{
lookupBatch
.
reset
();
}
}
}
private
Row
getNullRow
()
{
private
Row
getNullRow
()
{
...
@@ -657,6 +646,11 @@ public final class JoinBatch {
...
@@ -657,6 +646,11 @@ public final class JoinBatch {
this
.
filter
=
filter
;
this
.
filter
=
filter
;
}
}
@Override
public
String
getPlanSQL
()
{
return
"fake"
;
}
@Override
@Override
public
void
reset
()
{
public
void
reset
()
{
full
=
false
;
full
=
false
;
...
@@ -722,29 +716,36 @@ public final class JoinBatch {
...
@@ -722,29 +716,36 @@ public final class JoinBatch {
private
abstract
static
class
ViewIndexLookupBatchBase
<
R
extends
QueryRunnerBase
>
private
abstract
static
class
ViewIndexLookupBatchBase
<
R
extends
QueryRunnerBase
>
implements
IndexLookupBatch
{
implements
IndexLookupBatch
{
protected
final
ViewIndex
viewIndex
;
protected
final
ViewIndex
viewIndex
;
protected
final
ArrayList
<
Future
<
Cursor
>>
result
=
New
.
arrayList
();
private
final
ArrayList
<
Future
<
Cursor
>>
result
=
New
.
arrayList
();
protected
int
resultSize
;
private
int
resultSize
;
private
boolean
findCalled
;
protected
ViewIndexLookupBatchBase
(
ViewIndex
viewIndex
)
{
protected
ViewIndexLookupBatchBase
(
ViewIndex
viewIndex
)
{
this
.
viewIndex
=
viewIndex
;
this
.
viewIndex
=
viewIndex
;
}
}
@Override
public
String
getPlanSQL
()
{
return
"view"
;
}
protected
abstract
boolean
collectSearchRows
(
R
r
);
protected
abstract
boolean
collectSearchRows
(
R
r
);
protected
abstract
R
newQueryRunner
();
protected
abstract
R
newQueryRunner
();
protected
abstract
void
startQueryRunners
();
protected
abstract
void
startQueryRunners
(
int
resultSize
);
protected
final
boolean
resetAfterFind
()
{
protected
final
boolean
resetAfterFind
()
{
if
(
resultSize
<
0
)
{
if
(!
findCalled
)
{
// method find was called, we need to reset futures to initial state for reuse
return
false
;
for
(
int
i
=
0
,
size
=
-
resultSize
;
i
<
size
;
i
++)
{
queryRunner
(
i
).
reset
();
}
resultSize
=
0
;
return
true
;
}
}
return
false
;
findCalled
=
false
;
// method find was called, we need to reset futures to initial state for reuse
for
(
int
i
=
0
;
i
<
resultSize
;
i
++)
{
queryRunner
(
i
).
reset
();
}
resultSize
=
0
;
return
true
;
}
}
@SuppressWarnings
(
"unchecked"
)
@SuppressWarnings
(
"unchecked"
)
...
@@ -790,12 +791,9 @@ public final class JoinBatch {
...
@@ -790,12 +791,9 @@ public final class JoinBatch {
if
(
resultSize
==
0
)
{
if
(
resultSize
==
0
)
{
return
Collections
.
emptyList
();
return
Collections
.
emptyList
();
}
}
startQueryRunners
();
findCalled
=
true
;
List
<
Future
<
Cursor
>>
list
=
resultSize
==
result
.
size
()
?
startQueryRunners
(
resultSize
);
result
:
result
.
subList
(
0
,
resultSize
);
return
resultSize
==
result
.
size
()
?
result
:
result
.
subList
(
0
,
resultSize
);
// mark that method find was called
resultSize
=
-
resultSize
;
return
list
;
}
}
}
}
...
@@ -852,17 +850,16 @@ public final class JoinBatch {
...
@@ -852,17 +850,16 @@ public final class JoinBatch {
@Override
@Override
public
boolean
isBatchFull
()
{
public
boolean
isBatchFull
()
{
assert
resultSize
>=
0
;
return
top
.
isBatchFull
();
return
top
.
isBatchFull
();
}
}
@Override
@Override
protected
void
startQueryRunners
()
{
protected
void
startQueryRunners
(
int
resultSize
)
{
// we do batched find only for top table filter and then lazily run the ViewIndex query
// we do batched find only for top table filter and then lazily run the ViewIndex query
// for each received top future cursor
// for each received top future cursor
List
<
Future
<
Cursor
>>
topFutureCursors
=
top
.
find
();
List
<
Future
<
Cursor
>>
topFutureCursors
=
top
.
find
();
if
(
topFutureCursors
.
size
()
!=
resultSize
)
{
if
(
topFutureCursors
.
size
()
!=
resultSize
)
{
throw
DbException
.
throwInternalError
(
"Unexpected result size: "
+
result
.
size
()
+
throw
DbException
.
throwInternalError
(
"Unexpected result size: "
+
topFutureCursors
.
size
()
+
", expected :"
+
resultSize
);
", expected :"
+
resultSize
);
}
}
for
(
int
i
=
0
;
i
<
resultSize
;
i
++)
{
for
(
int
i
=
0
;
i
<
resultSize
;
i
++)
{
...
@@ -976,15 +973,18 @@ public final class JoinBatch {
...
@@ -976,15 +973,18 @@ public final class JoinBatch {
}
}
@Override
@Override
protected
void
startQueryRunners
()
{
protected
void
startQueryRunners
(
int
resultSize
)
{
for
(
int
i
=
0
;
i
<
filters
.
size
();
i
++)
{
for
(
int
f
=
0
;
f
<
filters
.
size
();
f
++)
{
List
<
Future
<
Cursor
>>
topFutureCursors
=
filters
.
get
(
i
).
find
();
List
<
Future
<
Cursor
>>
topFutureCursors
=
filters
.
get
(
f
).
find
();
for
(
int
j
=
0
,
k
=
0
;
j
<
resultSize
;
j
++)
{
int
r
=
0
,
c
=
0
;
Future
<
Cursor
>[]
cs
=
queryRunner
(
j
).
topFutureCursors
;
for
(;
r
<
resultSize
;
r
++)
{
if
(
cs
[
j
]
==
null
)
{
Future
<
Cursor
>[]
cs
=
queryRunner
(
r
).
topFutureCursors
;
cs
[
j
]
=
topFutureCursors
.
get
(
k
++);
if
(
cs
[
f
]
==
null
)
{
cs
[
f
]
=
topFutureCursors
.
get
(
c
++);
}
}
}
}
assert
r
==
resultSize
;
assert
c
==
topFutureCursors
.
size
();
}
}
}
}
}
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/table/TableFilter.java
浏览文件 @
58425db8
...
@@ -269,8 +269,10 @@ public class TableFilter implements ColumnResolver {
...
@@ -269,8 +269,10 @@ public class TableFilter implements ColumnResolver {
/**
/**
* Prepare reading rows. This method will remove all index conditions that
* Prepare reading rows. This method will remove all index conditions that
* can not be used, and optimize the conditions.
* can not be used, and optimize the conditions.
*
* @param parse if we are parsing sub-query
*/
*/
public
void
prepare
()
{
public
void
prepare
(
boolean
parse
)
{
// forget all unused index conditions
// forget all unused index conditions
// the indexConditions list may be modified here
// the indexConditions list may be modified here
for
(
int
i
=
0
;
i
<
indexConditions
.
size
();
i
++)
{
for
(
int
i
=
0
;
i
<
indexConditions
.
size
();
i
++)
{
...
@@ -289,19 +291,21 @@ public class TableFilter implements ColumnResolver {
...
@@ -289,19 +291,21 @@ public class TableFilter implements ColumnResolver {
if
(
SysProperties
.
CHECK
&&
nestedJoin
==
this
)
{
if
(
SysProperties
.
CHECK
&&
nestedJoin
==
this
)
{
DbException
.
throwInternalError
(
"self join"
);
DbException
.
throwInternalError
(
"self join"
);
}
}
nestedJoin
.
prepare
();
nestedJoin
.
prepare
(
parse
);
}
}
if
(
join
!=
null
)
{
if
(
join
!=
null
)
{
if
(
SysProperties
.
CHECK
&&
join
==
this
)
{
if
(
SysProperties
.
CHECK
&&
join
==
this
)
{
DbException
.
throwInternalError
(
"self join"
);
DbException
.
throwInternalError
(
"self join"
);
}
}
join
.
prepare
();
join
.
prepare
(
parse
);
}
}
if
(
filterCondition
!=
null
)
{
if
(!
parse
)
{
filterCondition
=
filterCondition
.
optimize
(
session
);
if
(
filterCondition
!=
null
)
{
}
filterCondition
=
filterCondition
.
optimize
(
session
);
if
(
joinCondition
!=
null
)
{
}
joinCondition
=
joinCondition
.
optimize
(
session
);
if
(
joinCondition
!=
null
)
{
joinCondition
=
joinCondition
.
optimize
(
session
);
}
}
}
}
}
...
@@ -784,11 +788,16 @@ public class TableFilter implements ColumnResolver {
...
@@ -784,11 +788,16 @@ public class TableFilter implements ColumnResolver {
buff
.
append
(
'\n'
);
buff
.
append
(
'\n'
);
StatementBuilder
planBuff
=
new
StatementBuilder
();
StatementBuilder
planBuff
=
new
StatementBuilder
();
if
(
joinBatch
!=
null
)
{
if
(
joinBatch
!=
null
)
{
if
(
joinBatch
.
isBatchedIndex
(
joinFilterId
))
{
IndexLookupBatch
lookupBatch
=
joinBatch
.
getLookupBatch
(
joinFilterId
);
planBuff
.
append
(
"batched:true "
);
if
(
lookupBatch
==
null
)
{
}
else
if
(
joinFilterId
!=
0
)
{
if
(
joinFilterId
!=
0
)
{
// top table filter does not need to fake batching, it works as usual in this case
throw
DbException
.
throwInternalError
();
planBuff
.
append
(
"batched:fake "
);
}
}
else
{
planBuff
.
append
(
"batched:"
);
String
batchPlan
=
lookupBatch
.
getPlanSQL
();
planBuff
.
append
(
batchPlan
);
planBuff
.
append
(
" "
);
}
}
}
}
planBuff
.
append
(
index
.
getPlanSQL
());
planBuff
.
append
(
index
.
getPlanSQL
());
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/db/TestTableEngines.java
浏览文件 @
58425db8
...
@@ -24,6 +24,7 @@ import java.util.concurrent.ExecutorService;
...
@@ -24,6 +24,7 @@ import java.util.concurrent.ExecutorService;
import
java.util.concurrent.Executors
;
import
java.util.concurrent.Executors
;
import
java.util.concurrent.Future
;
import
java.util.concurrent.Future
;
import
java.util.concurrent.ThreadFactory
;
import
java.util.concurrent.ThreadFactory
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
org.h2.api.TableEngine
;
import
org.h2.api.TableEngine
;
import
org.h2.command.ddl.CreateTableData
;
import
org.h2.command.ddl.CreateTableData
;
import
org.h2.command.dml.OptimizerHints
;
import
org.h2.command.dml.OptimizerHints
;
...
@@ -36,6 +37,7 @@ import org.h2.index.Index;
...
@@ -36,6 +37,7 @@ import org.h2.index.Index;
import
org.h2.index.IndexLookupBatch
;
import
org.h2.index.IndexLookupBatch
;
import
org.h2.index.IndexType
;
import
org.h2.index.IndexType
;
import
org.h2.index.SingleRowCursor
;
import
org.h2.index.SingleRowCursor
;
import
org.h2.jdbc.JdbcConnection
;
import
org.h2.message.DbException
;
import
org.h2.message.DbException
;
import
org.h2.result.Row
;
import
org.h2.result.Row
;
import
org.h2.result.SearchRow
;
import
org.h2.result.SearchRow
;
...
@@ -383,10 +385,24 @@ public class TestTableEngines extends TestBase {
...
@@ -383,10 +385,24 @@ public class TestTableEngines extends TestBase {
deleteDb
(
"testSubQueryInfo"
);
deleteDb
(
"testSubQueryInfo"
);
}
}
private
void
setBatchingEnabled
(
Statement
stat
,
boolean
enabled
)
throws
SQLException
{
stat
.
execute
(
"SET BATCH_JOINS "
+
enabled
);
if
(!
config
.
networked
)
{
Session
s
=
(
Session
)
((
JdbcConnection
)
stat
.
getConnection
()).
getSession
();
assertEquals
(
enabled
,
s
.
isJoinBatchEnabled
());
}
}
private
void
testBatchedJoin
()
throws
SQLException
{
private
void
testBatchedJoin
()
throws
SQLException
{
deleteDb
(
"t
ableEngine
"
);
deleteDb
(
"t
estBatchedJoin
"
);
Connection
conn
=
getConnection
(
"t
ableEngine;OPTIMIZE_REUSE_RESULTS=0
"
);
Connection
conn
=
getConnection
(
"t
estBatchedJoin;OPTIMIZE_REUSE_RESULTS=0;BATCH_JOINS=1
"
);
Statement
stat
=
conn
.
createStatement
();
Statement
stat
=
conn
.
createStatement
();
if
(!
config
.
networked
)
{
Session
s
=
(
Session
)
((
JdbcConnection
)
conn
).
getSession
();
assertTrue
(
s
.
isJoinBatchEnabled
());
}
setBatchingEnabled
(
stat
,
false
);
setBatchingEnabled
(
stat
,
true
);
TreeSetIndex
.
exec
=
Executors
.
newFixedThreadPool
(
8
,
new
ThreadFactory
()
{
TreeSetIndex
.
exec
=
Executors
.
newFixedThreadPool
(
8
,
new
ThreadFactory
()
{
@Override
@Override
...
@@ -399,6 +415,9 @@ public class TestTableEngines extends TestBase {
...
@@ -399,6 +415,9 @@ public class TestTableEngines extends TestBase {
enableJoinReordering
(
false
);
enableJoinReordering
(
false
);
try
{
try
{
doTestBatchedJoinSubQueryUnion
(
stat
);
TreeSetIndex
.
lookupBatches
.
set
(
0
);
doTestBatchedJoin
(
stat
,
1
,
0
,
0
);
doTestBatchedJoin
(
stat
,
1
,
0
,
0
);
doTestBatchedJoin
(
stat
,
0
,
1
,
0
);
doTestBatchedJoin
(
stat
,
0
,
1
,
0
);
doTestBatchedJoin
(
stat
,
0
,
0
,
1
);
doTestBatchedJoin
(
stat
,
0
,
0
,
1
);
...
@@ -429,11 +448,13 @@ public class TestTableEngines extends TestBase {
...
@@ -429,11 +448,13 @@ public class TestTableEngines extends TestBase {
doTestBatchedJoin
(
stat
,
0
,
0
,
5
);
doTestBatchedJoin
(
stat
,
0
,
0
,
5
);
doTestBatchedJoin
(
stat
,
0
,
8
,
1
);
doTestBatchedJoin
(
stat
,
0
,
8
,
1
);
doTestBatchedJoin
(
stat
,
0
,
2
,
1
);
doTestBatchedJoin
(
stat
,
0
,
2
,
1
);
assertTrue
(
TreeSetIndex
.
lookupBatches
.
get
()
>
0
);
}
finally
{
}
finally
{
enableJoinReordering
(
true
);
enableJoinReordering
(
true
);
TreeSetIndex
.
exec
.
shutdownNow
();
TreeSetIndex
.
exec
.
shutdownNow
();
}
}
deleteDb
(
"t
ableEngine
"
);
deleteDb
(
"t
estBatchedJoin
"
);
}
}
/**
/**
...
@@ -447,7 +468,64 @@ public class TestTableEngines extends TestBase {
...
@@ -447,7 +468,64 @@ public class TestTableEngines extends TestBase {
}
}
OptimizerHints
.
set
(
hints
);
OptimizerHints
.
set
(
hints
);
}
}
private
void
checkPlan
(
Statement
stat
,
String
sql
)
throws
SQLException
{
ResultSet
rs
=
stat
.
executeQuery
(
"EXPLAIN "
+
sql
);
assertTrue
(
rs
.
next
());
String
plan
=
rs
.
getString
(
1
);
assertEquals
(
normalize
(
sql
),
normalize
(
plan
));
}
private
static
String
normalize
(
String
sql
)
{
sql
=
sql
.
replace
(
'\n'
,
' '
);
return
sql
.
replaceAll
(
"\\s+"
,
" "
).
trim
();
}
private
void
doTestBatchedJoinSubQueryUnion
(
Statement
stat
)
throws
SQLException
{
String
engine
=
'"'
+
TreeSetIndexTableEngine
.
class
.
getName
()
+
'"'
;
stat
.
execute
(
"CREATE TABLE t (a int, b int) ENGINE "
+
engine
);
TreeSetTable
t
=
TreeSetIndexTableEngine
.
created
;
stat
.
execute
(
"CREATE INDEX T_IDX_A ON t(a)"
);
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
(
"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
+
")"
);
}
checkPlan
(
stat
,
"SELECT 1 FROM PUBLIC.T T1 /* PUBLIC.\"scan\" */ "
+
"INNER JOIN PUBLIC.T T2 /* batched:test PUBLIC.T_IDX_B: B = T1.A */ "
+
"ON 1=1 WHERE T1.A = T2.B"
);
checkPlan
(
stat
,
"SELECT 1 FROM PUBLIC.T T1 /* PUBLIC.\"scan\" */ "
+
"INNER JOIN PUBLIC.T T2 /* batched:test PUBLIC.T_IDX_B: B = T1.A */ "
+
"ON 1=1 /* WHERE T1.A = T2.B */ "
+
"INNER JOIN PUBLIC.T T3 /* batched:test PUBLIC.T_IDX_B: B = T2.A */ "
+
"ON 1=1 WHERE (T2.A = T3.B) AND (T1.A = T2.B)"
);
checkPlan
(
stat
,
"SELECT 1 FROM PUBLIC.T T1 /* PUBLIC.\"scan\" */ "
+
"INNER JOIN PUBLIC.U /* batched:fake PUBLIC.U_IDX_A: A = T1.A */ "
+
"ON 1=1 /* WHERE T1.A = U.A */ "
+
"INNER JOIN PUBLIC.T T2 /* batched:test PUBLIC.T_IDX_B: B = U.B */ "
+
"ON 1=1 WHERE (T1.A = U.A) AND (U.B = T2.B)"
);
checkPlan
(
stat
,
"SELECT 1 FROM ( SELECT A FROM PUBLIC.T ) Z "
+
"/* SELECT A FROM PUBLIC.T /++ PUBLIC.\"scan\" ++/ */ "
+
"INNER JOIN PUBLIC.T /* batched:test PUBLIC.T_IDX_B: B = Z.A */ "
+
"ON 1=1 WHERE Z.A = T.B"
);
checkPlan
(
stat
,
"SELECT 1 FROM PUBLIC.T /* PUBLIC.\"scan\" */ "
+
"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"
);
stat
.
execute
(
"DROP TABLE T"
);
stat
.
execute
(
"DROP TABLE U"
);
}
private
void
doTestBatchedJoin
(
Statement
stat
,
int
...
batchSizes
)
throws
SQLException
{
private
void
doTestBatchedJoin
(
Statement
stat
,
int
...
batchSizes
)
throws
SQLException
{
ArrayList
<
TreeSetTable
>
tables
=
New
.
arrayList
(
batchSizes
.
length
);
ArrayList
<
TreeSetTable
>
tables
=
New
.
arrayList
(
batchSizes
.
length
);
...
@@ -501,6 +579,9 @@ public class TestTableEngines extends TestBase {
...
@@ -501,6 +579,9 @@ public class TestTableEngines extends TestBase {
fail
();
fail
();
}
}
}
}
for
(
int
i
=
0
;
i
<
batchSizes
.
length
;
i
++)
{
stat
.
executeUpdate
(
"DROP TABLE IF EXISTS T"
+
i
);
}
}
}
private
static
void
assert0
(
boolean
condition
,
String
message
)
{
private
static
void
assert0
(
boolean
condition
,
String
message
)
{
...
@@ -512,7 +593,15 @@ public class TestTableEngines extends TestBase {
...
@@ -512,7 +593,15 @@ public class TestTableEngines extends TestBase {
private
static
void
setBatchSize
(
ArrayList
<
TreeSetTable
>
tables
,
int
...
batchSizes
)
{
private
static
void
setBatchSize
(
ArrayList
<
TreeSetTable
>
tables
,
int
...
batchSizes
)
{
for
(
int
i
=
0
;
i
<
batchSizes
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
batchSizes
.
length
;
i
++)
{
int
batchSize
=
batchSizes
[
i
];
int
batchSize
=
batchSizes
[
i
];
for
(
Index
idx
:
tables
.
get
(
i
).
getIndexes
())
{
setBatchSize
(
tables
.
get
(
i
),
batchSize
);
}
}
private
static
void
setBatchSize
(
TreeSetTable
t
,
int
batchSize
)
{
if
(
t
.
getIndexes
()
==
null
)
{
t
.
scan
.
preferedBatchSize
=
batchSize
;
}
else
{
for
(
Index
idx
:
t
.
getIndexes
())
{
((
TreeSetIndex
)
idx
).
preferedBatchSize
=
batchSize
;
((
TreeSetIndex
)
idx
).
preferedBatchSize
=
batchSize
;
}
}
}
}
...
@@ -1115,6 +1204,8 @@ public class TestTableEngines extends TestBase {
...
@@ -1115,6 +1204,8 @@ public class TestTableEngines extends TestBase {
* An index that internally uses a tree set.
* An index that internally uses a tree set.
*/
*/
private
static
class
TreeSetIndex
extends
BaseIndex
implements
Comparator
<
SearchRow
>
{
private
static
class
TreeSetIndex
extends
BaseIndex
implements
Comparator
<
SearchRow
>
{
private
static
AtomicInteger
lookupBatches
=
new
AtomicInteger
();
/**
/**
* Executor service to test batched joins.
* Executor service to test batched joins.
*/
*/
...
@@ -1145,9 +1236,18 @@ public class TestTableEngines extends TestBase {
...
@@ -1145,9 +1236,18 @@ public class TestTableEngines extends TestBase {
public
IndexLookupBatch
createLookupBatch
(
final
TableFilter
filter
)
{
public
IndexLookupBatch
createLookupBatch
(
final
TableFilter
filter
)
{
assert
filter
.
getMasks
()
!=
null
||
"scan"
.
equals
(
getName
());
assert
filter
.
getMasks
()
!=
null
||
"scan"
.
equals
(
getName
());
final
int
preferedSize
=
preferedBatchSize
;
final
int
preferedSize
=
preferedBatchSize
;
return
preferedSize
==
0
?
null
:
new
IndexLookupBatch
()
{
if
(
preferedSize
==
0
)
{
return
null
;
}
lookupBatches
.
incrementAndGet
();
return
new
IndexLookupBatch
()
{
List
<
SearchRow
>
searchRows
=
New
.
arrayList
();
List
<
SearchRow
>
searchRows
=
New
.
arrayList
();
@Override
public
String
getPlanSQL
()
{
return
"test"
;
}
@Override
public
boolean
isBatchFull
()
{
@Override
public
boolean
isBatchFull
()
{
return
searchRows
.
size
()
>=
preferedSize
*
2
;
return
searchRows
.
size
()
>=
preferedSize
*
2
;
}
}
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论