Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
58425db8
提交
58425db8
authored
11月 23, 2015
作者:
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
());
}
}
}
}
}
...
...
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
;
...
...
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
...
...
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
();
...
...
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
;
...
...
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
;
}
}
...
...
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
...
...
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.
*/
*/
...
...
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
();
}
}
}
}
}
}
...
...
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
());
...
...
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
;
}
}
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论