Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
bd37e682
提交
bd37e682
authored
9 年前
作者:
S.Vladykin
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Sub-query info added for cost calculation.
上级
84fd6dae
隐藏空白字符变更
内嵌
并排
正在显示
9 个修改的文件
包含
194 行增加
和
37 行删除
+194
-37
Optimizer.java
h2/src/main/org/h2/command/dml/Optimizer.java
+25
-9
Select.java
h2/src/main/org/h2/command/dml/Select.java
+6
-4
Session.java
h2/src/main/org/h2/engine/Session.java
+29
-1
Index.java
h2/src/main/org/h2/index/Index.java
+0
-2
IndexLookupBatch.java
h2/src/main/org/h2/index/IndexLookupBatch.java
+1
-1
ViewIndex.java
h2/src/main/org/h2/index/ViewIndex.java
+44
-17
SubQueryInfo.java
h2/src/main/org/h2/table/SubQueryInfo.java
+60
-0
TableView.java
h2/src/main/org/h2/table/TableView.java
+8
-2
TestTableEngines.java
h2/src/test/org/h2/test/db/TestTableEngines.java
+21
-1
没有找到文件。
h2/src/main/org/h2/command/dml/Optimizer.java
浏览文件 @
bd37e682
...
...
@@ -84,19 +84,26 @@ class Optimizer {
}
private
void
calculateBestPlan
()
{
start
=
System
.
currentTimeMillis
();
cost
=
-
1
;
if
(
filters
.
length
==
1
||
!
isJoinReorderingEnabled
())
{
testPlan
(
filters
);
}
else
if
(
filters
.
length
<=
MAX_BRUTE_FORCE_FILTERS
)
{
calculateBruteForceAll
();
}
else
{
calculateBruteForceSome
();
random
=
new
Random
(
0
);
calculateGenetic
();
start
=
System
.
currentTimeMillis
();
if
(
filters
.
length
<=
MAX_BRUTE_FORCE_FILTERS
)
{
calculateBruteForceAll
();
}
else
{
calculateBruteForceSome
();
random
=
new
Random
(
0
);
calculateGenetic
();
}
}
}
private
void
calculateFakePlan
()
{
cost
=
-
1
;
bestPlan
=
new
Plan
(
filters
,
filters
.
length
,
condition
);
}
private
boolean
canStop
(
int
x
)
{
if
((
x
&
127
)
==
0
)
{
long
t
=
System
.
currentTimeMillis
()
-
start
;
...
...
@@ -234,15 +241,24 @@ class Optimizer {
/**
* Calculate the best query plan to use.
*
* @param parse If we do not need to really get the best plan because it is view a parsing stage.
*/
void
optimize
()
{
calculateBestPlan
();
bestPlan
.
removeUnusableIndexConditions
();
void
optimize
(
boolean
parse
)
{
if
(
parse
)
{
calculateFakePlan
();
}
else
{
calculateBestPlan
();
bestPlan
.
removeUnusableIndexConditions
();
}
TableFilter
[]
f2
=
bestPlan
.
getFilters
();
topFilter
=
f2
[
0
];
for
(
int
i
=
0
;
i
<
f2
.
length
-
1
;
i
++)
{
f2
[
i
].
addJoin
(
f2
[
i
+
1
],
false
,
false
,
null
);
}
if
(
parse
)
{
return
;
}
for
(
TableFilter
f
:
f2
)
{
PlanItem
item
=
bestPlan
.
getItem
(
f
);
f
.
setPlanItem
(
item
);
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/command/dml/Select.java
浏览文件 @
bd37e682
...
...
@@ -863,7 +863,7 @@ public class Select extends Query {
isQuickAggregateQuery
=
isEverything
(
optimizable
);
}
}
cost
=
preparePlan
();
cost
=
preparePlan
(
session
.
isParsingView
()
);
if
(
distinct
&&
session
.
getDatabase
().
getSettings
().
optimizeDistinct
&&
!
isGroupQuery
&&
filters
.
size
()
==
1
&&
expressions
.
size
()
==
1
&&
condition
==
null
)
{
...
...
@@ -967,7 +967,7 @@ public class Select extends Query {
}
}
private
double
preparePlan
()
{
private
double
preparePlan
(
boolean
parse
)
{
TableFilter
[]
topArray
=
topFilters
.
toArray
(
new
TableFilter
[
topFilters
.
size
()]);
for
(
TableFilter
t
:
topArray
)
{
...
...
@@ -975,13 +975,15 @@ public class Select extends Query {
}
Optimizer
optimizer
=
new
Optimizer
(
topArray
,
condition
,
session
);
optimizer
.
optimize
();
optimizer
.
optimize
(
parse
);
topTableFilter
=
optimizer
.
getTopFilter
();
double
planCost
=
optimizer
.
getCost
();
setEvaluatableRecursive
(
topTableFilter
);
topTableFilter
.
prepare
();
if
(!
parse
)
{
topTableFilter
.
prepare
();
}
return
planCost
;
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/engine/Session.java
浏览文件 @
bd37e682
...
...
@@ -5,13 +5,13 @@
*/
package
org
.
h2
.
engine
;
import
java.util.ArrayDeque
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.Iterator
;
import
java.util.LinkedList
;
import
java.util.Random
;
import
org.h2.api.ErrorCode
;
import
org.h2.command.Command
;
import
org.h2.command.CommandInterface
;
...
...
@@ -33,6 +33,7 @@ import org.h2.schema.Schema;
import
org.h2.store.DataHandler
;
import
org.h2.store.InDoubtTransaction
;
import
org.h2.store.LobStorageFrontend
;
import
org.h2.table.SubQueryInfo
;
import
org.h2.table.Table
;
import
org.h2.util.New
;
import
org.h2.util.SmallLRUCache
;
...
...
@@ -109,6 +110,8 @@ public class Session extends SessionWithState {
private
final
int
queryCacheSize
;
private
SmallLRUCache
<
String
,
Command
>
queryCache
;
private
long
modificationMetaID
=
-
1
;
private
ArrayDeque
<
SubQueryInfo
>
subQueryInfoStack
=
new
ArrayDeque
<
SubQueryInfo
>();
private
int
parsingView
;
/**
* Temporary LOBs from result sets. Those are kept for some time. The
...
...
@@ -142,6 +145,31 @@ public class Session extends SessionWithState {
this
.
currentSchemaName
=
Constants
.
SCHEMA_MAIN
;
}
public
void
pushSubQueryInfo
(
SubQueryInfo
subQueryInfo
)
{
assert
subQueryInfo
!=
null
;
subQueryInfoStack
.
addLast
(
subQueryInfo
);
}
public
void
popSubQueryInfo
(
SubQueryInfo
subQueryInfo
)
{
SubQueryInfo
popped
=
subQueryInfoStack
.
pollLast
();
assert
popped
==
subQueryInfo
;
}
public
SubQueryInfo
getSubQueryInfo
()
{
return
subQueryInfoStack
.
peekLast
();
}
public
void
setParsingView
(
boolean
parsingView
)
{
// It can be recursive, thus implemented as counter.
this
.
parsingView
+=
parsingView
?
1
:
-
1
;
assert
this
.
parsingView
>=
0
;
}
public
boolean
isParsingView
()
{
assert
parsingView
>=
0
;
return
parsingView
!=
0
;
}
@Override
public
ArrayList
<
String
>
getClusterServers
()
{
return
new
ArrayList
<
String
>();
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/index/Index.java
浏览文件 @
bd37e682
...
...
@@ -5,8 +5,6 @@
*/
package
org
.
h2
.
index
;
import
java.util.List
;
import
java.util.concurrent.Future
;
import
org.h2.engine.Session
;
import
org.h2.result.Row
;
import
org.h2.result.SearchRow
;
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/index/IndexLookupBatch.java
浏览文件 @
bd37e682
...
...
@@ -17,7 +17,7 @@ import org.h2.result.SearchRow;
* Note that a single instance of {@link IndexLookupBatch} can be reused for multiple
* sequential batched lookups.
*
* @see Index#createLookupBatch(TableFilter)
* @see Index#createLookupBatch(
org.h2.table.
TableFilter)
* @author Sergi Vladykin
*/
public
interface
IndexLookupBatch
{
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/index/ViewIndex.java
浏览文件 @
bd37e682
...
...
@@ -6,8 +6,8 @@
package
org
.
h2
.
index
;
import
java.util.ArrayList
;
import
org.h2.api.ErrorCode
;
import
org.h2.command.Prepared
;
import
org.h2.command.dml.Query
;
import
org.h2.command.dml.SelectUnion
;
import
org.h2.engine.Constants
;
...
...
@@ -21,6 +21,7 @@ import org.h2.result.SearchRow;
import
org.h2.result.SortOrder
;
import
org.h2.table.Column
;
import
org.h2.table.IndexColumn
;
import
org.h2.table.SubQueryInfo
;
import
org.h2.table.TableFilter
;
import
org.h2.table.TableView
;
import
org.h2.util.IntArray
;
...
...
@@ -46,6 +47,14 @@ public class ViewIndex extends BaseIndex implements SpatialIndex {
private
Query
query
;
private
final
Session
createSession
;
/**
* Constructor for the original index in {@link TableView}.
*
* @param view the table view
* @param querySQL the query SQL
* @param originalParameters the original parameters
* @param recursive if the view is recursive
*/
public
ViewIndex
(
TableView
view
,
String
querySQL
,
ArrayList
<
Parameter
>
originalParameters
,
boolean
recursive
)
{
initBaseIndex
(
view
,
0
,
null
,
null
,
IndexType
.
createNonUnique
(
false
));
...
...
@@ -58,8 +67,19 @@ public class ViewIndex extends BaseIndex implements SpatialIndex {
this
.
indexMasks
=
null
;
}
/**
* Constructor for plan item generation. Over this index the query will be executed.
*
* @param view the table view
* @param index the view index
* @param session the session
* @param masks the masks
* @param filters table filters
* @param filter current filter
* @param sortOrder sort order
*/
public
ViewIndex
(
TableView
view
,
ViewIndex
index
,
Session
session
,
int
[]
masks
)
{
int
[]
masks
,
TableFilter
[]
filters
,
int
filter
,
SortOrder
sortOrder
)
{
initBaseIndex
(
view
,
0
,
null
,
null
,
IndexType
.
createNonUnique
(
false
));
this
.
view
=
view
;
this
.
querySQL
=
index
.
querySQL
;
...
...
@@ -69,7 +89,7 @@ public class ViewIndex extends BaseIndex implements SpatialIndex {
this
.
createSession
=
session
;
columns
=
new
Column
[
0
];
if
(!
recursive
)
{
query
=
getQuery
(
session
,
masks
);
query
=
getQuery
(
session
,
masks
,
filters
,
filter
,
sortOrder
);
}
}
...
...
@@ -129,20 +149,13 @@ public class ViewIndex extends BaseIndex implements SpatialIndex {
return
cachedCost
.
cost
;
}
}
Query
q
=
(
Query
)
session
.
prepare
(
querySQL
,
true
);
Query
q
=
prepareSubQuery
(
querySQL
,
session
,
masks
,
filters
,
filter
,
sortOrder
,
true
);
if
(
masks
!=
null
)
{
IntArray
paramIndex
=
new
IntArray
();
for
(
int
i
=
0
;
i
<
masks
.
length
;
i
++)
{
int
mask
=
masks
[
i
];
for
(
int
idx
=
0
;
idx
<
masks
.
length
;
idx
++)
{
int
mask
=
masks
[
idx
];
if
(
mask
==
0
)
{
continue
;
}
paramIndex
.
add
(
i
);
}
int
len
=
paramIndex
.
size
();
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
int
idx
=
paramIndex
.
get
(
i
);
int
mask
=
masks
[
idx
];
int
nextParamIndex
=
q
.
getParameters
().
size
()
+
view
.
getParameterOffset
();
if
((
mask
&
IndexCondition
.
EQUALITY
)
!=
0
)
{
Parameter
param
=
new
Parameter
(
nextParamIndex
);
...
...
@@ -162,7 +175,7 @@ public class ViewIndex extends BaseIndex implements SpatialIndex {
}
}
String
sql
=
q
.
getPlanSQL
();
q
=
(
Query
)
session
.
prepare
(
sql
,
tru
e
);
q
=
prepareSubQuery
(
sql
,
session
,
masks
,
filters
,
filter
,
sortOrder
,
fals
e
);
}
double
cost
=
q
.
getCost
();
cachedCost
=
new
CostElement
();
...
...
@@ -182,6 +195,19 @@ public class ViewIndex extends BaseIndex implements SpatialIndex {
return
find
(
filter
.
getSession
(),
null
,
null
,
intersection
);
}
private
static
Query
prepareSubQuery
(
String
sql
,
Session
session
,
int
[]
masks
,
TableFilter
[]
filters
,
int
filter
,
SortOrder
sortOrder
,
boolean
preliminary
)
{
Prepared
p
;
SubQueryInfo
info
=
new
SubQueryInfo
(
masks
,
filters
,
filter
,
sortOrder
,
preliminary
);
session
.
pushSubQueryInfo
(
info
);
try
{
p
=
session
.
prepare
(
sql
,
true
);
}
finally
{
session
.
popSubQueryInfo
(
info
);
}
return
(
Query
)
p
;
}
private
Cursor
find
(
Session
session
,
SearchRow
first
,
SearchRow
last
,
SearchRow
intersection
)
{
if
(
recursive
)
{
...
...
@@ -284,8 +310,9 @@ public class ViewIndex extends BaseIndex implements SpatialIndex {
param
.
setValue
(
v
);
}
private
Query
getQuery
(
Session
session
,
int
[]
masks
)
{
Query
q
=
(
Query
)
session
.
prepare
(
querySQL
,
true
);
private
Query
getQuery
(
Session
session
,
int
[]
masks
,
TableFilter
[]
filters
,
int
filter
,
SortOrder
sortOrder
)
{
Query
q
=
prepareSubQuery
(
querySQL
,
session
,
masks
,
filters
,
filter
,
sortOrder
,
true
);
if
(
masks
==
null
)
{
return
q
;
}
...
...
@@ -368,7 +395,7 @@ public class ViewIndex extends BaseIndex implements SpatialIndex {
}
String
sql
=
q
.
getPlanSQL
();
q
=
(
Query
)
session
.
prepare
(
sql
,
tru
e
);
q
=
prepareSubQuery
(
sql
,
session
,
masks
,
filters
,
filter
,
sortOrder
,
fals
e
);
return
q
;
}
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/table/SubQueryInfo.java
0 → 100644
浏览文件 @
bd37e682
/*
* Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
table
;
import
org.h2.result.SortOrder
;
/**
* Information about current sub-query being prepared.
*
* @author Sergi Vladykin
*/
public
class
SubQueryInfo
{
private
int
[]
masks
;
private
TableFilter
[]
filters
;
private
int
filter
;
private
SortOrder
sortOrder
;
private
boolean
preliminary
;
/**
* @param masks index conditions masks
* @param filters table filters
* @param filter current filter
* @param sortOrder sort order
* @param preliminary if this is a preliminary query optimization
* without global conditions
*/
public
SubQueryInfo
(
int
[]
masks
,
TableFilter
[]
filters
,
int
filter
,
SortOrder
sortOrder
,
boolean
preliminary
)
{
this
.
masks
=
masks
;
this
.
filters
=
filters
;
this
.
filter
=
filter
;
this
.
sortOrder
=
sortOrder
;
this
.
preliminary
=
preliminary
;
}
public
int
[]
getMasks
()
{
return
masks
;
}
public
TableFilter
[]
getFilters
()
{
return
filters
;
}
public
int
getFilter
()
{
return
filter
;
}
public
SortOrder
getSortOrder
()
{
return
sortOrder
;
}
public
boolean
isPreliminary
()
{
return
preliminary
;
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/table/TableView.java
浏览文件 @
bd37e682
...
...
@@ -103,7 +103,13 @@ public class TableView extends Table {
}
private
static
Query
compileViewQuery
(
Session
session
,
String
sql
)
{
Prepared
p
=
session
.
prepare
(
sql
);
Prepared
p
;
session
.
setParsingView
(
true
);
try
{
p
=
session
.
prepare
(
sql
);
}
finally
{
session
.
setParsingView
(
false
);
}
if
(!(
p
instanceof
Query
))
{
throw
DbException
.
getSyntaxError
(
sql
,
0
);
}
...
...
@@ -241,7 +247,7 @@ public class TableView extends Table {
// We cannot hold the lock during the ViewIndex creation or we risk ABBA
// deadlocks if the view creation calls back into H2 via something like
// a FunctionTable.
ViewIndex
i2
=
new
ViewIndex
(
this
,
index
,
session
,
masks
);
ViewIndex
i2
=
new
ViewIndex
(
this
,
index
,
session
,
masks
,
filters
,
filter
,
sortOrder
);
synchronized
(
this
)
{
// have to check again in case another session has beat us to it
ViewIndex
i3
=
indexCache
.
get
(
cacheKey
);
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/db/TestTableEngines.java
浏览文件 @
bd37e682
...
...
@@ -70,6 +70,7 @@ public class TestTableEngines extends TestBase {
@Override
public
void
test
()
throws
Exception
{
testSubQueryInfo
();
testEarlyFilter
();
testEngineParams
();
testSimpleQuery
();
...
...
@@ -342,7 +343,21 @@ public class TestTableEngines extends TestBase {
deleteDb
(
"tableEngine"
);
}
private
void
testSubQueryInfo
()
throws
SQLException
{
deleteDb
(
"testSubQueryInfo"
);
Connection
conn
=
getConnection
(
"testSubQueryInfo"
);
Statement
stat
=
conn
.
createStatement
();
stat
.
execute
(
"create table SUB_QUERY_TEST(id int primary key, name varchar) ENGINE \""
+
TreeSetIndexTableEngine
.
class
.
getName
()
+
"\""
);
stat
.
execute
(
"create table t1(id int, birthday date)"
);
stat
.
executeQuery
(
"select t1.birthday from t1, "
+
"(select t2.id from sub_query_test t2, "
+
"(select t3.id from sub_query_test t3 where t3.name = '') t4 "
+
"where t2.id = t4.id) t5 where t1.id = t5.id"
);
deleteDb
(
"testSubQueryInfo"
);
}
private
void
testBatchedJoin
()
throws
SQLException
{
deleteDb
(
"tableEngine"
);
Connection
conn
=
getConnection
(
"tableEngine;OPTIMIZE_REUSE_RESULTS=0"
);
...
...
@@ -1207,6 +1222,11 @@ public class TestTableEngines extends TestBase {
@Override
public
double
getCost
(
Session
session
,
int
[]
masks
,
TableFilter
[]
filters
,
int
filter
,
SortOrder
sortOrder
)
{
if
(
getTable
().
getName
().
equals
(
"SUB_QUERY_TEST"
))
{
if
(
session
.
getSubQueryInfo
()
==
null
)
{
throw
new
IllegalStateException
(
"No qubquery info found."
);
}
}
return
getCostRangeIndex
(
masks
,
set
.
size
(),
filters
,
filter
,
sortOrder
);
}
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论