提交 cb88fe35 authored 作者: Sergi Vladykin's avatar Sergi Vladykin

Fix for minimal covering index selection in query plan

上级 cb1a382d
...@@ -274,10 +274,10 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index { ...@@ -274,10 +274,10 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index {
/* /*
* The (20-x) calculation makes sure that when we pick a covering * The (20-x) calculation makes sure that when we pick a covering
* index, we pick the covering index that has the smallest number of * index, we pick the covering index that has the smallest number of
* columns. This is faster because a smaller index will fit into * columns (the more columns we have in index - the higher cost).
* fewer data blocks. * This is faster because a smaller index will fit into fewer data blocks.
*/ */
rc = rowsCost + sortingCost + (20 - columns.length); rc = rowsCost + sortingCost + columns.length;
} }
return rc; return rc;
} }
......
...@@ -41,6 +41,8 @@ public class TestCases extends TestBase { ...@@ -41,6 +41,8 @@ public class TestCases extends TestBase {
@Override @Override
public void test() throws Exception { public void test() throws Exception {
testMinimalCoveringIndexPlan();
testMinMaxDirectLookupIndex();
testReferenceLaterTable(); testReferenceLaterTable();
testAutoCommitInDatabaseURL(); testAutoCommitInDatabaseURL();
testReferenceableIndexUsage(); testReferenceableIndexUsage();
...@@ -1717,6 +1719,96 @@ public class TestCases extends TestBase { ...@@ -1717,6 +1719,96 @@ public class TestCases extends TestBase {
assertEquals("Lob file was not deleted: " + list, 0, list.size()); assertEquals("Lob file was not deleted: " + list, 0, list.size());
} }
private void testMinimalCoveringIndexPlan() throws SQLException {
deleteDb("cases");
Connection conn = getConnection("cases");
Statement stat = conn.createStatement();
stat.execute("create table t(a int, b int, c int)");
stat.execute("create index a_idx on t(a)");
stat.execute("create index b_idx on t(b)");
stat.execute("create index ab_idx on t(a, b)");
stat.execute("create index abc_idx on t(a, b, c)");
ResultSet rs;
String plan;
rs = stat.executeQuery("explain select a from t");
assertTrue(rs.next());
plan = rs.getString(1);
assertContains(plan, "/* PUBLIC.A_IDX */");
rs.close();
rs = stat.executeQuery("explain select b from t");
assertTrue(rs.next());
plan = rs.getString(1);
assertContains(plan, "/* PUBLIC.B_IDX */");
rs.close();
rs = stat.executeQuery("explain select b, a from t");
assertTrue(rs.next());
plan = rs.getString(1);
assertContains(plan, "/* PUBLIC.AB_IDX */");
rs.close();
rs = stat.executeQuery("explain select b, a, c from t");
assertTrue(rs.next());
plan = rs.getString(1);
assertContains(plan, "/* PUBLIC.ABC_IDX */");
rs.close();
conn.close();
}
private void testMinMaxDirectLookupIndex() throws SQLException {
deleteDb("cases");
Connection conn = getConnection("cases");
Statement stat = conn.createStatement();
stat.execute("create table t(a int, b int)");
stat.execute("create index b_idx on t(b desc)");
stat.execute("create index ab_idx on t(a, b)");
final int count = 100;
PreparedStatement p = conn.prepareStatement("insert into t values (?,?)");
for (int i = 0; i <= count; i++) {
p.setInt(1, i);
p.setInt(2, count - i);
assertEquals(1, p.executeUpdate());
}
p.close();
ResultSet rs;
String plan;
rs = stat.executeQuery("select max(b) from t");
assertTrue(rs.next());
assertEquals(count, rs.getInt(1));
rs.close();
rs = stat.executeQuery("explain select max(b) from t");
assertTrue(rs.next());
plan = rs.getString(1);
assertContains(plan, "/* PUBLIC.B_IDX */");
assertContains(plan, "/* direct lookup */");
rs.close();
rs = stat.executeQuery("select min(b) from t");
assertTrue(rs.next());
assertEquals(0, rs.getInt(1));
rs.close();
rs = stat.executeQuery("explain select min(b) from t");
assertTrue(rs.next());
plan = rs.getString(1);
assertContains(plan, "/* PUBLIC.B_IDX */");
assertContains(plan, "/* direct lookup */");
rs.close();
conn.close();
}
private void testDeleteTop() throws SQLException { private void testDeleteTop() throws SQLException {
deleteDb("cases"); deleteDb("cases");
Connection conn = getConnection("cases"); Connection conn = getConnection("cases");
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论