Skip to content

Commit 6c9560e

Browse files
committed
feat: support index cover & fix is_null can't use index
1 parent b9e77c7 commit 6c9560e

File tree

15 files changed

+955
-174
lines changed

15 files changed

+955
-174
lines changed

src/execution/dql/index_scan.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,31 @@ use crate::planner::operator::table_scan::TableScanOperator;
44
use crate::storage::{Iter, StatisticsMetaCache, TableCache, Transaction, ViewCache};
55
use crate::throw;
66
use crate::types::index::IndexMetaRef;
7+
use crate::types::serialize::TupleValueSerializableImpl;
78

89
pub(crate) struct IndexScan {
910
op: TableScanOperator,
1011
index_by: IndexMetaRef,
1112
ranges: Vec<Range>,
13+
covered_deserializers: Option<Vec<TupleValueSerializableImpl>>,
1214
}
1315

14-
impl From<(TableScanOperator, IndexMetaRef, Range)> for IndexScan {
15-
fn from((op, index_by, range): (TableScanOperator, IndexMetaRef, Range)) -> Self {
16+
impl
17+
From<(
18+
TableScanOperator,
19+
IndexMetaRef,
20+
Range,
21+
Option<Vec<TupleValueSerializableImpl>>,
22+
)> for IndexScan
23+
{
24+
fn from(
25+
(op, index_by, range, covered_deserializers): (
26+
TableScanOperator,
27+
IndexMetaRef,
28+
Range,
29+
Option<Vec<TupleValueSerializableImpl>>,
30+
),
31+
) -> Self {
1632
let ranges = match range {
1733
Range::SortedRanges(ranges) => ranges,
1834
range => vec![range],
@@ -22,6 +38,7 @@ impl From<(TableScanOperator, IndexMetaRef, Range)> for IndexScan {
2238
op,
2339
index_by,
2440
ranges,
41+
covered_deserializers,
2542
}
2643
}
2744
}
@@ -51,6 +68,7 @@ impl<'a, T: Transaction + 'a> ReadExecutor<'a, T> for IndexScan {
5168
self.index_by,
5269
self.ranges,
5370
with_pk,
71+
self.covered_deserializers,
5472
)
5573
);
5674

src/execution/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,11 @@ pub fn build_read<'a, T: Transaction + 'a>(
124124
if let Some(PhysicalOption::IndexScan(IndexInfo {
125125
meta,
126126
range: Some(range),
127+
covered_deserializers,
127128
})) = plan.physical_option
128129
{
129-
IndexScan::from((op, meta, range)).execute(cache, transaction)
130+
IndexScan::from((op, meta, range, covered_deserializers))
131+
.execute(cache, transaction)
130132
} else {
131133
SeqScan::from(op).execute(cache, transaction)
132134
}

src/optimizer/core/memo.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ mod tests {
212212
max: Bound::Unbounded,
213213
}
214214
])),
215+
covered_deserializers: None,
215216
}))
216217
);
217218

src/optimizer/rule/implementation/dql/table_scan.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,9 @@ impl<T: Transaction> ImplementationRule<T> for IndexScanImplementation {
7979
{
8080
let mut row_count = statistics_meta.collect_count(range)?;
8181

82-
if !matches!(index_info.meta.ty, IndexType::PrimaryKey { .. }) {
82+
if index_info.covered_deserializers.is_none()
83+
&& !matches!(index_info.meta.ty, IndexType::PrimaryKey { .. })
84+
{
8385
// need to return table query(non-covering index)
8486
row_count *= 2;
8587
}

src/optimizer/rule/normalization/pushdown_predicates.rs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -215,12 +215,17 @@ impl NormalizationRule for PushPredicateIntoScan {
215215
fn apply(&self, node_id: HepNodeId, graph: &mut HepGraph) -> Result<(), DatabaseError> {
216216
if let Operator::Filter(op) = graph.operator(node_id).clone() {
217217
if let Some(child_id) = graph.eldest_child_at(node_id) {
218-
if let Operator::TableScan(child_op) = graph.operator_mut(child_id) {
219-
//FIXME: now only support `unique` and `primary key`
220-
for IndexInfo { meta, range } in &mut child_op.index_infos {
218+
if let Operator::TableScan(scan_op) = graph.operator_mut(child_id) {
219+
for IndexInfo {
220+
meta,
221+
range,
222+
covered_deserializers,
223+
} in &mut scan_op.index_infos
224+
{
221225
if range.is_some() {
222226
continue;
223227
}
228+
// range detach
224229
*range = match meta.ty {
225230
IndexType::PrimaryKey { is_multiple: false }
226231
| IndexType::Unique
@@ -232,6 +237,17 @@ impl NormalizationRule for PushPredicateIntoScan {
232237
Self::composite_range(&op, meta)?
233238
}
234239
};
240+
// try index covered
241+
let mut deserializers = Vec::with_capacity(scan_op.columns.len());
242+
for column_id in &meta.column_ids {
243+
for column in scan_op.columns.values() {
244+
if column.id().map(|id| &id == column_id).unwrap_or(false) {
245+
deserializers.push(column.datatype().serializable());
246+
}
247+
}
248+
}
249+
*covered_deserializers =
250+
(!deserializers.is_empty()).then_some(deserializers);
235251
}
236252
}
237253
}

src/planner/operator/table_scan.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ impl TableScanOperator {
4848
.map(|meta| IndexInfo {
4949
meta: meta.clone(),
5050
range: None,
51+
covered_deserializers: None,
5152
})
5253
.collect_vec();
5354

src/storage/memory.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,7 @@ mod native_tests {
349349
max: Bound::Included(DataValue::Int32(2)),
350350
}],
351351
true,
352+
None,
352353
)?;
353354

354355
let mut result = Vec::new();

0 commit comments

Comments
 (0)