Skip to content

Commit c66585a

Browse files
committed
perf: tpcc
- `Tuple` id to use mapping to get the primary key - `Executor` uses `*mut Transaction` to avoid materialization problems caused by mutable references
1 parent cfab5b4 commit c66585a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+730
-632
lines changed

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
[package]
44
name = "fnck_sql"
5-
version = "0.0.7"
5+
version = "0.0.8"
66
edition = "2021"
77
authors = ["Kould <[email protected]>", "Xwg <[email protected]>"]
88
description = "SQL as a Function for Rust"

README.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,13 @@ run `cargo run -p tpcc --release` to run tpcc
7373
- Tips: TPC-C currently only supports single thread
7474
```shell
7575
<90th Percentile RT (MaxRT)>
76-
New-Order : 0.003 (0.006)
76+
New-Order : 0.003 (0.012)
7777
Payment : 0.001 (0.003)
78-
Order-Status : 0.062 (0.188)
79-
Delivery : 0.022 (0.052)
78+
Order-Status : 0.054 (0.188)
79+
Delivery : 0.021 (0.049)
8080
Stock-Level : 0.004 (0.006)
8181
<TpmC>
82-
6669 Tpmc
82+
7345 Tpmc
8383
```
8484
#### 👉[check more](tpcc/README.md)
8585

src/binder/copy.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,9 @@ impl<T: Transaction> Binder<'_, '_, T> {
8080
return Err(DatabaseError::UnsupportedStmt("'COPY SOURCE'".to_string()));
8181
}
8282
};
83+
let table_name = Arc::new(lower_case_name(&table_name)?);
8384

84-
if let Some(table) = self.context.table(Arc::new(table_name.to_string()))? {
85+
if let Some(table) = self.context.table(table_name.clone())? {
8586
let schema_ref = table.schema_ref().clone();
8687
let ext_source = ExtSource {
8788
path: match target {
@@ -107,7 +108,7 @@ impl<T: Transaction> Binder<'_, '_, T> {
107108
Operator::CopyFromFile(CopyFromFileOperator {
108109
source: ext_source,
109110
schema_ref,
110-
table: table_name.to_string(),
111+
table: table_name,
111112
}),
112113
Childrens::None,
113114
))

src/catalog/table.rs

+31-6
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use std::{slice, vec};
1111
use ulid::Generator;
1212

1313
pub type TableName = Arc<String>;
14+
pub type PrimaryKeyIndices = Arc<Vec<usize>>;
1415

1516
#[derive(Debug, Clone, PartialEq)]
1617
pub struct TableCatalog {
@@ -22,6 +23,7 @@ pub struct TableCatalog {
2223

2324
schema_ref: SchemaRef,
2425
primary_keys: Vec<(usize, ColumnRef)>,
26+
primary_key_indices: PrimaryKeyIndices,
2527
primary_key_type: Option<LogicalType>,
2628
}
2729

@@ -32,6 +34,10 @@ pub struct TableMeta {
3234
}
3335

3436
impl TableCatalog {
37+
pub(crate) fn name(&self) -> &TableName {
38+
&self.name
39+
}
40+
3541
pub(crate) fn get_unique_index(&self, col_id: &ColumnId) -> Option<&IndexMetaRef> {
3642
self.indexes
3743
.iter()
@@ -79,6 +85,10 @@ impl TableCatalog {
7985
&self.primary_keys
8086
}
8187

88+
pub(crate) fn primary_keys_indices(&self) -> &PrimaryKeyIndices {
89+
&self.primary_key_indices
90+
}
91+
8292
pub(crate) fn types(&self) -> Vec<LogicalType> {
8393
self.columns()
8494
.map(|column| column.datatype().clone())
@@ -186,6 +196,7 @@ impl TableCatalog {
186196
indexes: vec![],
187197
schema_ref: Arc::new(vec![]),
188198
primary_keys: vec![],
199+
primary_key_indices: Default::default(),
189200
primary_key_type: None,
190201
};
191202
let mut generator = Generator::new();
@@ -194,7 +205,11 @@ impl TableCatalog {
194205
.add_column(col_catalog, &mut generator)
195206
.unwrap();
196207
}
197-
table_catalog.primary_keys = Self::build_primary_keys(&table_catalog.schema_ref);
208+
let (primary_keys, primary_key_indices) =
209+
Self::build_primary_keys(&table_catalog.schema_ref);
210+
211+
table_catalog.primary_keys = primary_keys;
212+
table_catalog.primary_key_indices = primary_key_indices;
198213

199214
Ok(table_catalog)
200215
}
@@ -216,7 +231,7 @@ impl TableCatalog {
216231
columns.insert(column_id, i);
217232
}
218233
let schema_ref = Arc::new(column_refs.clone());
219-
let primary_keys = Self::build_primary_keys(&schema_ref);
234+
let (primary_keys, primary_key_indices) = Self::build_primary_keys(&schema_ref);
220235

221236
Ok(TableCatalog {
222237
name,
@@ -225,12 +240,18 @@ impl TableCatalog {
225240
indexes,
226241
schema_ref,
227242
primary_keys,
243+
primary_key_indices,
228244
primary_key_type: None,
229245
})
230246
}
231247

232-
fn build_primary_keys(schema_ref: &Arc<Vec<ColumnRef>>) -> Vec<(usize, ColumnRef)> {
233-
schema_ref
248+
fn build_primary_keys(
249+
schema_ref: &Arc<Vec<ColumnRef>>,
250+
) -> (Vec<(usize, ColumnRef)>, PrimaryKeyIndices) {
251+
let mut primary_keys = Vec::new();
252+
let mut primary_key_indices = Vec::new();
253+
254+
for (_, (i, column)) in schema_ref
234255
.iter()
235256
.enumerate()
236257
.filter_map(|(i, column)| {
@@ -240,8 +261,12 @@ impl TableCatalog {
240261
.map(|p_i| (p_i, (i, column.clone())))
241262
})
242263
.sorted_by_key(|(p_i, _)| *p_i)
243-
.map(|(_, entry)| entry)
244-
.collect_vec()
264+
{
265+
primary_key_indices.push(i);
266+
primary_keys.push((i, column));
267+
}
268+
269+
(primary_keys, Arc::new(primary_key_indices))
245270
}
246271
}
247272

src/db.rs

+6-12
Original file line numberDiff line numberDiff line change
@@ -532,10 +532,10 @@ pub(crate) mod test {
532532
);
533533
assert_eq!(
534534
iter.next().unwrap()?,
535-
Tuple {
536-
id: None,
537-
values: vec![DataValue::Date32(Some(Local::now().num_days_from_ce()))],
538-
}
535+
Tuple::new(
536+
None,
537+
vec![DataValue::Date32(Some(Local::now().num_days_from_ce()))]
538+
)
539539
);
540540
assert!(iter.next().is_none());
541541

@@ -562,17 +562,11 @@ pub(crate) mod test {
562562
assert_eq!(iter.schema(), &Arc::new(vec![ColumnRef::from(column)]));
563563
assert_eq!(
564564
iter.next().unwrap()?,
565-
Tuple {
566-
id: None,
567-
values: vec![DataValue::Int32(Some(3))],
568-
}
565+
Tuple::new(None, vec![DataValue::Int32(Some(3))])
569566
);
570567
assert_eq!(
571568
iter.next().unwrap()?,
572-
Tuple {
573-
id: None,
574-
values: vec![DataValue::Int32(Some(4))],
575-
}
569+
Tuple::new(None, vec![DataValue::Int32(Some(4))])
576570
);
577571
Ok(())
578572
}

src/execution/ddl/add_column.rs

+14-7
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ impl<'a, T: Transaction + 'a> WriteExecutor<'a, T> for AddColumn {
2727
fn execute_mut(
2828
mut self,
2929
cache: (&'a TableCache, &'a ViewCache, &'a StatisticsMetaCache),
30-
transaction: &'a mut T,
30+
transaction: *mut T,
3131
) -> Executor<'a> {
3232
Box::new(
3333
#[coroutine]
@@ -55,7 +55,7 @@ impl<'a, T: Transaction + 'a> WriteExecutor<'a, T> for AddColumn {
5555

5656
if let Some(value) = throw!(column.default_value()) {
5757
if let Some(unique_values) = &mut unique_values {
58-
unique_values.push((tuple.id.clone().unwrap(), value.clone()));
58+
unique_values.push((tuple.id().unwrap().clone(), value.clone()));
5959
}
6060
tuple.values.push(value);
6161
} else {
@@ -66,21 +66,28 @@ impl<'a, T: Transaction + 'a> WriteExecutor<'a, T> for AddColumn {
6666
drop(coroutine);
6767

6868
for tuple in tuples {
69-
throw!(transaction.append_tuple(table_name, tuple, &types, true));
69+
throw!(unsafe { &mut (*transaction) }
70+
.append_tuple(table_name, tuple, &types, true));
7071
}
71-
let col_id =
72-
throw!(transaction.add_column(cache.0, table_name, column, *if_not_exists));
72+
let col_id = throw!(unsafe { &mut (*transaction) }.add_column(
73+
cache.0,
74+
table_name,
75+
column,
76+
*if_not_exists
77+
));
7378

7479
// Unique Index
7580
if let (Some(unique_values), Some(unique_meta)) = (
7681
unique_values,
77-
throw!(transaction.table(cache.0, table_name.clone()))
82+
throw!(unsafe { &mut (*transaction) }.table(cache.0, table_name.clone()))
7883
.and_then(|table| table.get_unique_index(&col_id))
7984
.cloned(),
8085
) {
8186
for (tuple_id, value) in unique_values {
8287
let index = Index::new(unique_meta.id, &value, IndexType::Unique);
83-
throw!(transaction.add_index(table_name, index, &tuple_id));
88+
throw!(
89+
unsafe { &mut (*transaction) }.add_index(table_name, index, &tuple_id)
90+
);
8491
}
8592
}
8693

src/execution/ddl/create_index.rs

+15-15
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ impl<'a, T: Transaction + 'a> WriteExecutor<'a, T> for CreateIndex {
3030
fn execute_mut(
3131
mut self,
3232
cache: (&'a TableCache, &'a ViewCache, &'a StatisticsMetaCache),
33-
transaction: &'a mut T,
33+
transaction: *mut T,
3434
) -> Executor<'a> {
3535
Box::new(
3636
#[coroutine]
@@ -52,7 +52,7 @@ impl<'a, T: Transaction + 'a> WriteExecutor<'a, T> for CreateIndex {
5252
})
5353
.unzip();
5454
let schema = self.input.output_schema().clone();
55-
let index_id = match transaction.add_index_meta(
55+
let index_id = match unsafe { &mut (*transaction) }.add_index_meta(
5656
cache.0,
5757
&table_name,
5858
index_name,
@@ -69,29 +69,29 @@ impl<'a, T: Transaction + 'a> WriteExecutor<'a, T> for CreateIndex {
6969
}
7070
err => throw!(err),
7171
};
72-
let mut index_values = Vec::new();
7372
let mut coroutine = build_read(self.input, cache, transaction);
7473

7574
while let CoroutineState::Yielded(tuple) = Pin::new(&mut coroutine).resume(()) {
7675
let mut tuple: Tuple = throw!(tuple);
7776

78-
let tuple_id = if let Some(tuple_id) = tuple.id.take() {
79-
tuple_id
80-
} else {
77+
let Some(value) = DataValue::values_to_tuple(throw!(Projection::projection(
78+
&tuple,
79+
&column_exprs,
80+
&schema
81+
))) else {
8182
continue;
8283
};
83-
index_values.push((
84-
tuple_id,
85-
throw!(Projection::projection(&tuple, &column_exprs, &schema)),
86-
));
87-
}
88-
drop(coroutine);
89-
for (tuple_id, values) in index_values {
90-
let Some(value) = DataValue::values_to_tuple(values) else {
84+
let tuple_id = if let Some(tuple_id) = tuple.id().take() {
85+
tuple_id
86+
} else {
9187
continue;
9288
};
9389
let index = Index::new(index_id, &value, ty);
94-
throw!(transaction.add_index(table_name.as_str(), index, &tuple_id));
90+
throw!(unsafe { &mut (*transaction) }.add_index(
91+
table_name.as_str(),
92+
index,
93+
tuple_id
94+
));
9595
}
9696
yield Ok(TupleBuilder::build_result("1".to_string()));
9797
},

src/execution/ddl/create_table.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ impl<'a, T: Transaction + 'a> WriteExecutor<'a, T> for CreateTable {
1818
fn execute_mut(
1919
self,
2020
(table_cache, _, _): (&'a TableCache, &'a ViewCache, &'a StatisticsMetaCache),
21-
transaction: &'a mut T,
21+
transaction: *mut T,
2222
) -> Executor<'a> {
2323
Box::new(
2424
#[coroutine]
@@ -29,7 +29,7 @@ impl<'a, T: Transaction + 'a> WriteExecutor<'a, T> for CreateTable {
2929
if_not_exists,
3030
} = self.op;
3131

32-
let _ = throw!(transaction.create_table(
32+
let _ = throw!(unsafe { &mut (*transaction) }.create_table(
3333
table_cache,
3434
table_name.clone(),
3535
columns,

src/execution/ddl/create_view.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@ impl<'a, T: Transaction + 'a> WriteExecutor<'a, T> for CreateView {
1818
fn execute_mut(
1919
self,
2020
(_, view_cache, _): (&'a TableCache, &'a ViewCache, &'a StatisticsMetaCache),
21-
transaction: &'a mut T,
21+
transaction: *mut T,
2222
) -> Executor<'a> {
2323
Box::new(
2424
#[coroutine]
2525
move || {
2626
let CreateViewOperator { view, or_replace } = self.op;
2727

2828
let result_tuple = TupleBuilder::build_result(format!("{}", view.name));
29-
throw!(transaction.create_view(view_cache, view, or_replace));
29+
throw!(unsafe { &mut (*transaction) }.create_view(view_cache, view, or_replace));
3030

3131
yield Ok(result_tuple);
3232
},

src/execution/ddl/drop_column.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ impl<'a, T: Transaction + 'a> WriteExecutor<'a, T> for DropColumn {
2525
fn execute_mut(
2626
mut self,
2727
cache: (&'a TableCache, &'a ViewCache, &'a StatisticsMetaCache),
28-
transaction: &'a mut T,
28+
transaction: *mut T,
2929
) -> Executor<'a> {
3030
Box::new(
3131
#[coroutine]
@@ -67,9 +67,19 @@ impl<'a, T: Transaction + 'a> WriteExecutor<'a, T> for DropColumn {
6767
}
6868
drop(coroutine);
6969
for tuple in tuples {
70-
throw!(transaction.append_tuple(&table_name, tuple, &types, true));
70+
throw!(unsafe { &mut (*transaction) }.append_tuple(
71+
&table_name,
72+
tuple,
73+
&types,
74+
true
75+
));
7176
}
72-
throw!(transaction.drop_column(cache.0, cache.2, &table_name, &column_name));
77+
throw!(unsafe { &mut (*transaction) }.drop_column(
78+
cache.0,
79+
cache.2,
80+
&table_name,
81+
&column_name
82+
));
7383

7484
yield Ok(TupleBuilder::build_result("1".to_string()));
7585
} else if if_exists {

src/execution/ddl/drop_table.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ impl<'a, T: Transaction + 'a> WriteExecutor<'a, T> for DropTable {
1818
fn execute_mut(
1919
self,
2020
(table_cache, _, _): (&'a TableCache, &'a ViewCache, &'a StatisticsMetaCache),
21-
transaction: &'a mut T,
21+
transaction: *mut T,
2222
) -> Executor<'a> {
2323
Box::new(
2424
#[coroutine]
@@ -28,7 +28,11 @@ impl<'a, T: Transaction + 'a> WriteExecutor<'a, T> for DropTable {
2828
if_exists,
2929
} = self.op;
3030

31-
throw!(transaction.drop_table(table_cache, table_name.clone(), if_exists));
31+
throw!(unsafe { &mut (*transaction) }.drop_table(
32+
table_cache,
33+
table_name.clone(),
34+
if_exists
35+
));
3236

3337
yield Ok(TupleBuilder::build_result(format!("{}", table_name)));
3438
},

0 commit comments

Comments
 (0)