Unverified 提交 ba4dbc05 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov 提交者: GitHub

Merge pull request #1589 from katzyn/cost

Improve cost calculation for multi-column indexes
...@@ -168,12 +168,14 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index { ...@@ -168,12 +168,14 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index {
int totalSelectivity = 0; int totalSelectivity = 0;
long rowsCost = rowCount; long rowsCost = rowCount;
if (masks != null) { if (masks != null) {
for (int i = 0, len = columns.length; i < len; i++) { int i = 0, len = columns.length;
Column column = columns[i]; boolean tryAdditional = false;
while (i < len) {
Column column = columns[i++];
int index = column.getColumnId(); int index = column.getColumnId();
int mask = masks[index]; int mask = masks[index];
if ((mask & IndexCondition.EQUALITY) == IndexCondition.EQUALITY) { if ((mask & IndexCondition.EQUALITY) == IndexCondition.EQUALITY) {
if (i == columns.length - 1 && getIndexType().isUnique()) { if (i == len && getIndexType().isUnique()) {
rowsCost = 3; rowsCost = 3;
break; break;
} }
...@@ -185,18 +187,34 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index { ...@@ -185,18 +187,34 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index {
} }
rowsCost = 2 + Math.max(rowCount / distinctRows, 1); rowsCost = 2 + Math.max(rowCount / distinctRows, 1);
} else if ((mask & IndexCondition.RANGE) == IndexCondition.RANGE) { } else if ((mask & IndexCondition.RANGE) == IndexCondition.RANGE) {
rowsCost = 2 + rowCount / 4; rowsCost = 2 + rowsCost / 4;
tryAdditional = true;
break; break;
} else if ((mask & IndexCondition.START) == IndexCondition.START) { } else if ((mask & IndexCondition.START) == IndexCondition.START) {
rowsCost = 2 + rowCount / 3; rowsCost = 2 + rowsCost / 3;
tryAdditional = true;
break; break;
} else if ((mask & IndexCondition.END) == IndexCondition.END) { } else if ((mask & IndexCondition.END) == IndexCondition.END) {
rowsCost = rowCount / 3; rowsCost = rowsCost / 3;
tryAdditional = true;
break; break;
} else { } else {
if (mask == 0) {
// Adjust counter of used columns (i)
i--;
}
break; break;
} }
} }
// Some additional columns can still be used
if (tryAdditional) {
while (i < len && masks[columns[i].getColumnId()] != 0) {
i++;
rowsCost--;
}
}
// Increase cost of indexes with additional unused columns
rowsCost += len - i;
} }
// If the ORDER BY clause matches the ordering of this index, // If the ORDER BY clause matches the ordering of this index,
// it will be cheaper than another index, so adjust the cost // it will be cheaper than another index, so adjust the cost
......
...@@ -304,3 +304,49 @@ select 1 from test group by x; ...@@ -304,3 +304,49 @@ select 1 from test group by x;
drop table test; drop table test;
> ok > ok
CREATE TABLE TEST(A INT, B INT, C INT);
> ok
CREATE INDEX T_A1 ON TEST(A);
> ok
CREATE INDEX T_A_B ON TEST(A, B);
> ok
CREATE INDEX T_A_C ON TEST(A, C);
> ok
EXPLAIN SELECT * FROM TEST WHERE A = 0;
>> SELECT TEST.A, TEST.B, TEST.C FROM PUBLIC.TEST /* PUBLIC.T_A1: A = 0 */ WHERE A = 0
EXPLAIN SELECT * FROM TEST WHERE A = 0 AND B >= 0;
>> SELECT TEST.A, TEST.B, TEST.C FROM PUBLIC.TEST /* PUBLIC.T_A_B: A = 0 AND B >= 0 */ WHERE (A = 0) AND (B >= 0)
EXPLAIN SELECT * FROM TEST WHERE A > 0 AND B >= 0;
>> SELECT TEST.A, TEST.B, TEST.C FROM PUBLIC.TEST /* PUBLIC.T_A_B: A > 0 AND B >= 0 */ WHERE (A > 0) AND (B >= 0)
INSERT INTO TEST (SELECT X / 100, X, X FROM SYSTEM_RANGE(1, 3000));
> update count: 3000
EXPLAIN SELECT * FROM TEST WHERE A = 0;
>> SELECT TEST.A, TEST.B, TEST.C FROM PUBLIC.TEST /* PUBLIC.T_A1: A = 0 */ WHERE A = 0
EXPLAIN SELECT * FROM TEST WHERE A = 0 AND B >= 0;
>> SELECT TEST.A, TEST.B, TEST.C FROM PUBLIC.TEST /* PUBLIC.T_A_B: A = 0 AND B >= 0 */ WHERE (A = 0) AND (B >= 0)
EXPLAIN SELECT * FROM TEST WHERE A > 0 AND B >= 0;
>> SELECT TEST.A, TEST.B, TEST.C FROM PUBLIC.TEST /* PUBLIC.T_A_B: A > 0 AND B >= 0 */ WHERE (A > 0) AND (B >= 0)
-- Test that creation order of indexes has no effect
CREATE INDEX T_A2 ON TEST(A);
> ok
DROP INDEX T_A1;
> ok
EXPLAIN SELECT * FROM TEST WHERE A = 0;
>> SELECT TEST.A, TEST.B, TEST.C FROM PUBLIC.TEST /* PUBLIC.T_A2: A = 0 */ WHERE A = 0
DROP TABLE TEST;
> ok
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论