Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

planner: choose TableScan when use an empty index hint #12037

Merged
merged 15 commits into from
Sep 6, 2019
2 changes: 1 addition & 1 deletion planner/core/logical_plan_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -1973,7 +1973,7 @@ func (b *PlanBuilder) pushTableHints(hints []*ast.TableOptimizerHint, nodeType n
case HintStreamAgg:
preferAggType |= preferStreamAgg
case HintIndex:
if len(hint.Tables) != 0 && len(hint.Indexes) != 0 {
if len(hint.Tables) != 0 {
indexHintList = append(indexHintList, indexHintInfo{
tblName: hint.Tables[0].TableName,
indexHint: &ast.IndexHint{
Expand Down
10 changes: 10 additions & 0 deletions planner/core/logical_plans.go
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,16 @@ type accessPath struct {
partialIndexPaths []*accessPath
}

// getTablePath finds the TablePath from a group of accessPaths.
func getTablePath(paths []*accessPath) *accessPath {
for _, path := range paths {
if path.isTablePath {
return path
}
}
return nil
}

// deriveTablePathStats will fulfill the information that the accessPath need.
// And it will check whether the primary key is covered only by point query.
func (ds *DataSource) deriveTablePathStats(path *accessPath, conds []expression.Expression) (bool, error) {
Expand Down
10 changes: 10 additions & 0 deletions planner/core/physical_plan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ func (s *testPlanSuite) TestDAGPlanBuilderSimpleCase(c *C) {
sql: "select * from t t1 use index(c_d_e)",
best: "IndexLookUp(Index(t.c_d_e)[[NULL,+inf]], Table(t))",
},
{
sql: "select f from t use index() where f = 1",
best: "TableReader(Table(t)->Sel([eq(test.t.f, 1)]))",
},
// Test ts + Sort vs. DoubleRead + filter.
{
sql: "select a from t where a between 1 and 2 order by c",
Expand Down Expand Up @@ -1772,6 +1776,12 @@ func (s *testPlanSuite) TestIndexHint(c *C) {
best: "IndexLookUp(Index(t.f)[[NULL,+inf]], Table(t))",
hasWarn: false,
},
// use TablePath when the hint only contains table.
{
sql: "select /*+ INDEX(t) */ f from t where f > 10",
best: "TableReader(Table(t)->Sel([gt(test.t.f, 10)]))",
hasWarn: false,
},
// there will be a warning instead of error when index not exist
{
sql: "select /*+ INDEX(t, no_such_index) */ * from t",
Expand Down
9 changes: 9 additions & 0 deletions planner/core/planbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,15 @@ func (b *PlanBuilder) getPossibleAccessPaths(indexHints []*ast.IndexHint, tblInf
}

hasScanHint = true
if hint.IndexNames == nil && hint.HintType != ast.HintIgnore {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about adding a comment? From MySQL document:

It is syntactically valid to omit index_list for USE INDEX, which means “use no indexes.” Omitting index_list for FORCE INDEX or IGNORE INDEX is a syntax error.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed

// If indexNames is nil, choose TablePath.
// For example: `select a from t use index()`.
if path := getTablePath(publicPaths); path != nil {
hasUseOrForce = true
path.forced = true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need check whether is ignore or force.
Or you'll set table path as forced although no index is ignored by IGNORE INDEX()

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

available = append(available, path)
}
}
for _, idxName := range hint.IndexNames {
path := getPathByIndexName(publicPaths, idxName, tblInfo)
if path == nil {
Expand Down