Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
ab48ac15
提交
ab48ac15
authored
9 年前
作者:
S.Vladykin
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
new batched index lookup api
上级
21962651
隐藏空白字符变更
内嵌
并排
正在显示
5 个修改的文件
包含
150 行增加
和
106 行删除
+150
-106
BaseIndex.java
h2/src/main/org/h2/index/BaseIndex.java
+3
-8
Index.java
h2/src/main/org/h2/index/Index.java
+5
-21
MultiVersionIndex.java
h2/src/main/org/h2/index/MultiVersionIndex.java
+3
-7
TableFilter.java
h2/src/main/org/h2/table/TableFilter.java
+114
-66
TestTableEngines.java
h2/src/test/org/h2/test/db/TestTableEngines.java
+25
-4
没有找到文件。
h2/src/main/org/h2/index/BaseIndex.java
浏览文件 @
ab48ac15
...
...
@@ -427,13 +427,8 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index {
}
@Override
public
int
getPreferedLookupBatchSize
()
{
// No batched lookups supported by default.
return
0
;
}
@Override
public
List
<
Future
<
Cursor
>>
findBatched
(
TableFilter
filter
,
List
<
SearchRow
>
firstLastPairs
)
{
throw
DbException
.
throwInternalError
(
"Must not be called if getPreferedLookupBatchSize() is 0."
);
public
IndexLookupBatch
createLookupBatch
(
TableFilter
filter
)
{
// Lookup batching is not supported.
return
null
;
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/index/Index.java
浏览文件 @
ab48ac15
...
...
@@ -259,27 +259,11 @@ public interface Index extends SchemaObject {
void
setSortedInsertMode
(
boolean
sortedInsertMode
);
/**
*
If this index can do batched lookups, it may return it's preferred batch size,
*
otherwise it must return 0
.
*
Creates new lookup batch. Note that returned {@link IndexLookupBatch} instance
*
can be used multiple times
.
*
* @
return preferred batch size or 0 if lookup batching is not supported
* @
see #findBatched(TableFilter, Collection)
* @
param filter Table filter.
* @
return Created batch or {@code null} if batched lookup is not supported by this index.
*/
int
getPreferedLookupBatchSize
();
/**
* Do batched lookup over the given collection of {@link SearchRow} pairs as in
* {@link #find(TableFilter, SearchRow, SearchRow)}.
* <br/><br/>
* Correct implementation must always return number of future cursors equal to
* {@code firstLastPairs.size() / 2}. Instead of {@link Future} containing empty
* {@link Cursor} it is possible to put {@code null} in result list.
*
* @param filter the table filter
* @param firstLastPairs List of batched search row pairs as in
* {@link #find(TableFilter, SearchRow, SearchRow)}, the collection will be reused by H2,
* thus it makes sense to defensively copy contents if needed.
* @return batched cursors for respective search row pairs in the same order
*/
List
<
Future
<
Cursor
>>
findBatched
(
TableFilter
filter
,
List
<
SearchRow
>
firstLastPairs
);
IndexLookupBatch
createLookupBatch
(
TableFilter
filter
);
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/index/MultiVersionIndex.java
浏览文件 @
ab48ac15
...
...
@@ -389,12 +389,8 @@ public class MultiVersionIndex implements Index {
}
@Override
public
int
getPreferedLookupBatchSize
()
{
return
0
;
}
@Override
public
List
<
Future
<
Cursor
>>
findBatched
(
TableFilter
filter
,
List
<
SearchRow
>
firstLastPairs
)
{
throw
DbException
.
throwInternalError
(
"Must never be called."
);
public
IndexLookupBatch
createLookupBatch
(
TableFilter
filter
)
{
// Lookup batching is not supported.
return
null
;
}
}
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/table/TableFilter.java
浏览文件 @
ab48ac15
...
...
@@ -5,6 +5,7 @@
*/
package
org
.
h2
.
table
;
import
java.util.AbstractList
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Collections
;
...
...
@@ -23,6 +24,7 @@ import org.h2.expression.Expression;
import
org.h2.expression.ExpressionColumn
;
import
org.h2.index.Cursor
;
import
org.h2.index.Index
;
import
org.h2.index.IndexLookupBatch
;
import
org.h2.index.IndexCondition
;
import
org.h2.index.IndexCursor
;
import
org.h2.message.DbException
;
...
...
@@ -345,16 +347,22 @@ public class TableFilter implements ColumnResolver {
if
(
join
!=
null
)
{
batch
=
join
.
startQuery
(
s
);
}
if
(
batch
==
null
&&
index
.
getPreferedLookupBatchSize
()
!=
0
&&
select
!=
null
&&
select
.
getTopTableFilter
()
!=
this
)
{
batch
=
new
JoinBatch
(
join
);
IndexLookupBatch
lookupBatch
=
null
;
if
(
batch
==
null
&&
select
!=
null
&&
select
.
getTopTableFilter
()
!=
this
)
{
lookupBatch
=
index
.
createLookupBatch
(
this
);
if
(
lookupBatch
!=
null
)
{
batch
=
new
JoinBatch
(
join
);
}
}
if
(
batch
!=
null
)
{
if
(
nestedJoin
!=
null
)
{
throw
DbException
.
getUnsupportedException
(
"nested join with batched index"
);
}
if
(
lookupBatch
==
null
)
{
lookupBatch
=
index
.
createLookupBatch
(
this
);
}
joinBatch
=
batch
;
joinFilter
=
batch
.
register
(
this
);
joinFilter
=
batch
.
register
(
this
,
lookupBatch
);
}
return
batch
;
}
...
...
@@ -1126,11 +1134,12 @@ public class TableFilter implements ColumnResolver {
/**
* @param filter table filter
* @param lookupBatch lookup batch
*/
private
JoinFilter
register
(
TableFilter
filter
)
{
private
JoinFilter
register
(
TableFilter
filter
,
IndexLookupBatch
lookupBatch
)
{
assert
filter
!=
null
;
filtersCount
++;
return
top
=
new
JoinFilter
(
filter
,
top
);
return
top
=
new
JoinFilter
(
lookupBatch
,
filter
,
top
);
}
/**
...
...
@@ -1365,23 +1374,15 @@ public class TableFilter implements ColumnResolver {
*/
private
static
final
class
JoinFilter
{
final
TableFilter
filter
;
final
int
batchSize
;
final
JoinFilter
join
;
int
id
;
/**
* Search rows batch.
*/
final
ArrayList
<
SearchRow
>
searchRows
;
IndexLookupBatch
lookupBatch
;
private
JoinFilter
(
TableFilter
filter
,
JoinFilter
join
)
{
private
JoinFilter
(
IndexLookupBatch
lookupBatch
,
TableFilter
filter
,
JoinFilter
join
)
{
this
.
filter
=
filter
;
this
.
join
=
join
;
batchSize
=
filter
.
getIndex
().
getPreferedLookupBatchSize
();
if
(
batchSize
<
0
)
{
throw
DbException
.
throwInternalError
(
"Index with negative preferred batch size."
);
}
searchRows
=
New
.
arrayList
(
batchSize
==
0
?
2
:
Math
.
min
(
batchSize
*
2
,
32
));
this
.
lookupBatch
=
lookupBatch
!=
null
?
lookupBatch
:
new
FakeLookupBatch
(
filter
);
}
public
Row
getNullRow
()
{
...
...
@@ -1393,10 +1394,7 @@ public class TableFilter implements ColumnResolver {
}
private
boolean
isBatchFull
()
{
if
(
batchSize
==
0
)
{
return
searchRows
.
size
()
>=
2
;
}
return
searchRows
.
size
()
>=
batchSize
*
2
;
return
lookupBatch
.
isBatchFull
();
}
private
boolean
isOk
(
boolean
ignoreJoinCondition
)
{
...
...
@@ -1408,62 +1406,40 @@ public class TableFilter implements ColumnResolver {
private
boolean
collectSearchRows
()
{
assert
!
isBatchFull
();
filter
.
cursor
.
prepare
(
filter
.
session
,
filter
.
indexConditions
);
if
(
filter
.
cursor
.
isAlwaysFalse
())
{
IndexCursor
c
=
filter
.
cursor
;
c
.
prepare
(
filter
.
session
,
filter
.
indexConditions
);
if
(
c
.
isAlwaysFalse
())
{
return
false
;
}
searchRows
.
add
(
filter
.
cursor
.
getStart
());
searchRows
.
add
(
filter
.
cursor
.
getEnd
());
lookupBatch
.
addSearchRows
(
c
.
getStart
(),
c
.
getEnd
());
return
true
;
}
private
JoinRow
find
(
JoinRow
current
)
{
assert
current
!=
null
;
assert
(
searchRows
.
size
()
&
1
)
==
0
:
"searchRows & 1, "
+
searchRows
.
size
();
// searchRows are allowed to be empty when we have some null-rows and forced find call
if
(!
searchRows
.
isEmpty
())
{
assert
searchRows
.
size
()
>=
2
:
"searchRows >= 2, "
+
searchRows
.
size
();
List
<
Future
<
Cursor
>>
result
;
if
(
batchSize
==
0
)
{
assert
searchRows
.
size
()
==
2
:
"2"
;
Cursor
c
=
filter
.
index
.
find
(
filter
,
searchRows
.
get
(
0
),
searchRows
.
get
(
1
));
result
=
Collections
.<
Future
<
Cursor
>>
singletonList
(
new
DoneFuture
<
Cursor
>(
c
));
}
else
{
result
=
filter
.
index
.
findBatched
(
filter
,
searchRows
);
if
(
result
==
null
)
{
throw
DbException
.
throwInternalError
(
"Index.findBatched returned null"
);
}
// lookupBatch is allowed to be empty when we have some null-rows and forced find call
List
<
Future
<
Cursor
>>
result
=
lookupBatch
.
find
();
// go backwards and assign futures
for
(
int
i
=
result
.
size
();
i
>
0
;)
{
assert
current
.
isRow
(
id
-
1
);
if
(
current
.
row
(
id
)
==
EMPTY_CURSOR
)
{
// outer join support - skip row with existing empty cursor
current
=
current
.
prev
;
continue
;
}
if
(
result
.
size
()
!=
searchRows
.
size
()
>>>
1
)
{
throw
DbException
.
throwInternalError
(
"wrong number of futures"
);
assert
current
.
row
(
id
)
==
null
;
Future
<
Cursor
>
future
=
result
.
get
(--
i
);
if
(
future
==
null
)
{
current
.
updateRow
(
id
,
EMPTY_CURSOR
,
JoinRow
.
S_NULL
,
JoinRow
.
S_CURSOR
);
}
else
{
current
.
updateRow
(
id
,
future
,
JoinRow
.
S_NULL
,
JoinRow
.
S_FUTURE
);
}
searchRows
.
clear
();
// go backwards and assign futures
ListIterator
<
Future
<
Cursor
>>
iter
=
result
.
listIterator
(
result
.
size
());
for
(;;)
{
assert
current
.
isRow
(
id
-
1
);
if
(
current
.
row
(
id
)
==
EMPTY_CURSOR
)
{
// outer join support - skip row with existing empty cursor
current
=
current
.
prev
;
continue
;
}
assert
current
.
row
(
id
)
==
null
;
Future
<
Cursor
>
future
=
iter
.
previous
();
if
(
future
==
null
)
{
current
.
updateRow
(
id
,
EMPTY_CURSOR
,
JoinRow
.
S_NULL
,
JoinRow
.
S_CURSOR
);
}
else
{
current
.
updateRow
(
id
,
future
,
JoinRow
.
S_NULL
,
JoinRow
.
S_FUTURE
);
}
if
(
current
.
prev
==
null
||
!
iter
.
hasPrevious
())
{
break
;
}
current
=
current
.
prev
;
if
(
current
.
prev
==
null
||
i
==
0
)
{
break
;
}
current
=
current
.
prev
;
}
// handle empty cursors (because of outer joins) at the beginning
...
...
@@ -1611,4 +1587,76 @@ public class TableFilter implements ColumnResolver {
return
"JoinRow->"
+
Arrays
.
toString
(
row
);
}
}
/**
* Fake Lookup batch for indexes which do not support batching but have to participate
* in batched joins.
*/
private
static
class
FakeLookupBatch
implements
IndexLookupBatch
{
final
TableFilter
filter
;
SearchRow
first
;
SearchRow
last
;
boolean
full
;
final
List
<
Future
<
Cursor
>>
result
=
new
SingletonList
<
Future
<
Cursor
>>();
/**
* @param index Index.
*/
public
FakeLookupBatch
(
TableFilter
filter
)
{
this
.
filter
=
filter
;
}
@Override
public
void
addSearchRows
(
SearchRow
first
,
SearchRow
last
)
{
assert
!
full
;
this
.
first
=
first
;
this
.
last
=
last
;
full
=
true
;
}
@Override
public
boolean
isBatchFull
()
{
return
full
;
}
@Override
public
List
<
Future
<
Cursor
>>
find
()
{
if
(!
full
)
{
return
Collections
.
emptyList
();
}
Cursor
c
=
filter
.
getIndex
().
find
(
filter
,
first
,
last
);
result
.
set
(
0
,
new
DoneFuture
<
Cursor
>(
c
));
full
=
false
;
first
=
last
=
null
;
return
result
;
}
}
/**
* Simple singleton list.
*/
private
static
class
SingletonList
<
E
>
extends
AbstractList
<
E
>
{
private
E
element
;
@Override
public
E
get
(
int
index
)
{
assert
index
==
0
;
return
element
;
}
@Override
public
E
set
(
int
index
,
E
element
)
{
assert
index
==
0
;
this
.
element
=
element
;
return
null
;
}
@Override
public
int
size
()
{
return
1
;
}
}
}
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/db/TestTableEngines.java
浏览文件 @
ab48ac15
...
...
@@ -33,6 +33,7 @@ import org.h2.expression.Expression;
import
org.h2.index.BaseIndex
;
import
org.h2.index.Cursor
;
import
org.h2.index.Index
;
import
org.h2.index.IndexLookupBatch
;
import
org.h2.index.IndexType
;
import
org.h2.index.SingleRowCursor
;
import
org.h2.message.DbException
;
...
...
@@ -1094,11 +1095,31 @@ public class TestTableEngines extends TestBase {
}
@Override
public
int
getPreferedLookupBatchSize
()
{
return
preferedBatchSize
;
public
IndexLookupBatch
createLookupBatch
(
final
TableFilter
filter
)
{
final
int
preferedSize
=
preferedBatchSize
;
return
preferedSize
==
0
?
null
:
new
IndexLookupBatch
()
{
List
<
SearchRow
>
searchRows
=
New
.
arrayList
();
@Override
public
boolean
isBatchFull
()
{
return
searchRows
.
size
()
>=
preferedSize
*
2
;
}
@Override
public
List
<
Future
<
Cursor
>>
find
()
{
List
<
Future
<
Cursor
>>
res
=
findBatched
(
filter
,
searchRows
);
searchRows
.
clear
();
return
res
;
}
@Override
public
void
addSearchRows
(
SearchRow
first
,
SearchRow
last
)
{
assert
!
isBatchFull
();
searchRows
.
add
(
first
);
searchRows
.
add
(
last
);
}
};
}
@Override
public
List
<
Future
<
Cursor
>>
findBatched
(
final
TableFilter
filter
,
List
<
SearchRow
>
firstLastPairs
)
{
ArrayList
<
Future
<
Cursor
>>
result
=
New
.
arrayList
(
firstLastPairs
.
size
());
final
Random
rnd
=
new
Random
();
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论