Skip to content

Commit 3e8108b

Browse files
committed
Lift restriction that multi-col indices only allow = constraints #1317
benches
1 parent cd17e4c commit 3e8108b

File tree

11 files changed

+990
-589
lines changed

11 files changed

+990
-589
lines changed

crates/core/src/estimation.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ pub fn num_rows(tx: &Tx, expr: &QueryExpr) -> u64 {
1212
/// Use cardinality estimates to predict the total number of rows scanned by a query
1313
pub fn estimate_rows_scanned(tx: &Tx, plan: &PhysicalPlan) -> u64 {
1414
match plan {
15-
PhysicalPlan::TableScan(..) | PhysicalPlan::IxScan(..) => row_estimate(tx, plan),
15+
PhysicalPlan::TableScan(..) | PhysicalPlan::IxScan(..) | PhysicalPlan::IxScansAnd(_, _) => {
16+
row_estimate(tx, plan)
17+
}
1618
PhysicalPlan::Filter(input, _) => estimate_rows_scanned(tx, input).saturating_add(row_estimate(tx, input)),
1719
PhysicalPlan::NLJoin(lhs, rhs) => estimate_rows_scanned(tx, lhs)
1820
.saturating_add(estimate_rows_scanned(tx, rhs))
@@ -50,6 +52,7 @@ pub fn row_estimate(tx: &Tx, plan: &PhysicalPlan) -> u64 {
5052
// Use a row limit as the estimate if present
5153
PhysicalPlan::TableScan(TableScan { limit: Some(n), .. }, _)
5254
| PhysicalPlan::IxScan(IxScan { limit: Some(n), .. }, _) => *n,
55+
PhysicalPlan::IxScansAnd(idx, _) => idx.iter().map(|plan| row_estimate(tx, plan)).sum(),
5356
// Table scans return the number of rows in the table
5457
PhysicalPlan::TableScan(
5558
TableScan {

crates/core/src/sql/compiler.rs

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -456,8 +456,8 @@ Index Scan using Index test_b_idx_btree (test.b) on test
456456
"select * from test where b = 2 and a = 1",
457457
expect![
458458
r#"
459-
Index Scan using Index test_a_b_idx_btree (test.b, test.a) on test
460-
Index Cond: (test.b = U64(2), test.a = U64(1))
459+
Index Scan using Index test_a_b_idx_btree (test.a, test.b) on test
460+
Index Cond: (test.a = U64(1), test.b = U64(2))
461461
Output: test.a, test.b, test.c, test.d"#
462462
],
463463
);
@@ -513,15 +513,14 @@ Seq Scan on test
513513
db.create_table_for_test("test", schema, indexes)?;
514514

515515
let tx = begin_tx(&db);
516-
// TODO: Need support for index range scans.
517516
expect_query(
518517
&tx,
519518
"select * from test where b > 2",
520519
expect![
521520
r#"
522-
Seq Scan on test
523-
Output: test.a, test.b
524-
-> Filter: (test.b > U64(2))"#
521+
Index Scan using Index test_b_idx_btree (test.b) on test
522+
Index Cond: (test.b > U64(2))
523+
Output: test.a, test.b"#
525524
],
526525
);
527526

@@ -538,15 +537,15 @@ Seq Scan on test
538537
db.create_table_for_test("test", schema, indexes)?;
539538

540539
let tx = begin_tx(&db);
541-
//TODO(sql): Need support for index scans for ranges
542540
expect_query(
543541
&tx,
544542
"select * from test where b > 2 and b < 5",
545543
expect![
546544
r#"
547-
Seq Scan on test
545+
Index Scan using Index test_b_idx_btree (test.b) on test
546+
Index Cond: (test.b > U64(2))
548547
Output: test.a, test.b
549-
-> Filter: (test.b > U64(2) AND test.b < U64(5))"#
548+
-> Filter: (test.b < U64(5))"#
550549
],
551550
);
552551

@@ -563,17 +562,20 @@ Seq Scan on test
563562
db.create_table_for_test("test", schema, indexes)?;
564563

565564
let tx = begin_tx(&db);
566-
// Note, order matters - the equality condition occurs first which
567-
// means an index scan will be generated rather than the range condition.
568565
expect_query(
569566
&tx,
570-
"select * from test where a = 3 and b > 2 and b < 5",
567+
"select * from test where b > 2 and b < 5 and a = 3",
571568
expect![
572569
r#"
573-
Index Scan using Index test_a_idx_btree (test.a) on test
574-
Index Cond: (test.a = U64(3))
570+
Union
571+
-> Index Scan using Index test_a_idx_btree (test.a) on test
572+
Index Cond: (test.a = U64(3))
573+
Output: test.a, test.b
574+
-> Index Scan using Index test_b_idx_btree (test.b) on test
575+
Index Cond: (test.b > U64(2))
576+
Output: test.a, test.b
575577
Output: test.a, test.b
576-
-> Filter: (test.b < U64(5) AND test.b > U64(2))"#
578+
-> Filter: (test.b < U64(5))"#
577579
],
578580
);
579581

@@ -717,9 +719,9 @@ Hash Join: Lhs
717719
Index Cond: (lhs.a = U64(3))
718720
Output: lhs.a, lhs.b
719721
-> Hash Build: rhs.b
720-
-> Seq Scan on rhs
721-
Output: rhs.b, rhs.c
722-
-> Filter: (rhs.c < U64(4))"#
722+
-> Index Scan using Index rhs_c_idx_btree (rhs.c) on rhs
723+
Index Cond: (rhs.c < U64(4))
724+
Output: rhs.b, rhs.c"#
723725
],
724726
);
725727

@@ -756,9 +758,10 @@ Index Join: Rhs on lhs
756758
Inner Unique: false
757759
Join Cond: (rhs.b = lhs.b)
758760
Output: lhs.a, lhs.b
759-
-> Seq Scan on rhs
761+
-> Index Scan using Index rhs_c_idx_btree (rhs.c) on rhs
762+
Index Cond: (rhs.c > U64(2))
760763
Output: rhs.b, rhs.c, rhs.d
761-
-> Filter: (rhs.c > U64(2) AND rhs.c < U64(4) AND rhs.d = U64(3))"#
764+
-> Filter: (rhs.c < U64(4) AND rhs.d = U64(3))"#
762765
],
763766
);
764767

@@ -795,8 +798,8 @@ Index Join: Rhs on lhs
795798
Inner Unique: false
796799
Join Cond: (rhs.b = lhs.b)
797800
Output: lhs.a, lhs.b
798-
-> Index Scan using Index rhs_b_c_idx_btree (rhs.c, rhs.b) on rhs
799-
Index Cond: (rhs.c = U64(2), rhs.b = U64(4))
801+
-> Index Scan using Index rhs_b_c_idx_btree (rhs.b, rhs.c) on rhs
802+
Index Cond: (rhs.b = U64(4), rhs.c = U64(2))
800803
Output: rhs.b, rhs.c, rhs.d
801804
-> Filter: (rhs.d = U64(3))"#
802805
],

0 commit comments

Comments
 (0)