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: rename stable-result-mode to ordered-result-mode (#26093) #26133

Merged
merged 11 commits into from
Jul 14, 2021
18 changes: 9 additions & 9 deletions executor/set_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -429,15 +429,15 @@ func (s *testSuite5) TestSetVar(c *C) {
tk.MustExec("set session tidb_slow_log_masking = 1")
tk.MustQuery(`select @@session.tidb_slow_log_masking;`).Check(testkit.Rows("1"))

// test for tidb_enable_stable_result_mode
tk.MustQuery(`select @@tidb_enable_stable_result_mode`).Check(testkit.Rows("0"))
tk.MustExec(`set global tidb_enable_stable_result_mode = 1`)
tk.MustQuery(`select @@global.tidb_enable_stable_result_mode`).Check(testkit.Rows("1"))
tk.MustExec(`set global tidb_enable_stable_result_mode = 0`)
tk.MustQuery(`select @@global.tidb_enable_stable_result_mode`).Check(testkit.Rows("0"))
tk.MustExec(`set tidb_enable_stable_result_mode=1`)
tk.MustQuery(`select @@global.tidb_enable_stable_result_mode`).Check(testkit.Rows("0"))
tk.MustQuery(`select @@tidb_enable_stable_result_mode`).Check(testkit.Rows("1"))
// test for tidb_enable_ordered_result_mode
tk.MustQuery(`select @@tidb_enable_ordered_result_mode`).Check(testkit.Rows("0"))
tk.MustExec(`set global tidb_enable_ordered_result_mode = 1`)
tk.MustQuery(`select @@global.tidb_enable_ordered_result_mode`).Check(testkit.Rows("1"))
tk.MustExec(`set global tidb_enable_ordered_result_mode = 0`)
tk.MustQuery(`select @@global.tidb_enable_ordered_result_mode`).Check(testkit.Rows("0"))
tk.MustExec(`set tidb_enable_ordered_result_mode=1`)
tk.MustQuery(`select @@global.tidb_enable_ordered_result_mode`).Check(testkit.Rows("0"))
tk.MustQuery(`select @@tidb_enable_ordered_result_mode`).Check(testkit.Rows("1"))
}

func (s *testSuite5) TestTruncateIncorrectIntSessionVar(c *C) {
Expand Down
2 changes: 1 addition & 1 deletion planner/core/optimizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const (
var optRuleList = []logicalOptRule{
&gcSubstituter{},
&columnPruner{},
&resultsStabilizer{},
&resultReorder{},
&buildKeySolver{},
&decorrelateSolver{},
&aggregationEliminator{},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,29 +21,30 @@ import (
)

/*
resultsStabilizer stabilizes query results.
resultReorder reorder query results.
NOTE: it's not a common rule for all queries, it's specially implemented for a few customers.
Results of some queries are not stable, for example:

Results of some queries are not ordered, for example:
create table t (a int); insert into t values (1), (2); select a from t;
In the case above, the result can be `1 2` or `2 1`, which is not stable.
This rule stabilizes results by modifying or injecting a Sort operator:
In the case above, the result can be `1 2` or `2 1`, which is not ordered.
This rule reorders results by modifying or injecting a Sort operator:
1. iterate the plan from the root, and ignore all input-order operators (Sel/Proj/Limit);
2. when meeting the first non-input-order operator,
2.1. if it's a Sort, update it by appending all output columns into its order-by list,
2.2. otherwise, inject a new Sort upon this operator.
*/
type resultsStabilizer struct {
type resultReorder struct {
}

func (rs *resultsStabilizer) optimize(ctx context.Context, lp LogicalPlan) (LogicalPlan, error) {
stable := rs.completeSort(lp)
if !stable {
func (rs *resultReorder) optimize(ctx context.Context, lp LogicalPlan) (LogicalPlan, error) {
ordered := rs.completeSort(lp)
if !ordered {
lp = rs.injectSort(lp)
}
return lp, nil
}

func (rs *resultsStabilizer) completeSort(lp LogicalPlan) bool {
func (rs *resultReorder) completeSort(lp LogicalPlan) bool {
if rs.isInputOrderKeeper(lp) {
return rs.completeSort(lp.Children()[0])
} else if sort, ok := lp.(*LogicalSort); ok {
Expand All @@ -68,7 +69,7 @@ func (rs *resultsStabilizer) completeSort(lp LogicalPlan) bool {
return false
}

func (rs *resultsStabilizer) injectSort(lp LogicalPlan) LogicalPlan {
func (rs *resultReorder) injectSort(lp LogicalPlan) LogicalPlan {
if rs.isInputOrderKeeper(lp) {
lp.SetChildren(rs.injectSort(lp.Children()[0]))
return lp
Expand All @@ -89,7 +90,7 @@ func (rs *resultsStabilizer) injectSort(lp LogicalPlan) LogicalPlan {
return sort
}

func (rs *resultsStabilizer) isInputOrderKeeper(lp LogicalPlan) bool {
func (rs *resultReorder) isInputOrderKeeper(lp LogicalPlan) bool {
switch lp.(type) {
case *LogicalSelection, *LogicalProjection, *LogicalLimit:
return true
Expand All @@ -98,7 +99,7 @@ func (rs *resultsStabilizer) isInputOrderKeeper(lp LogicalPlan) bool {
}

// extractHandleCols does the best effort to get the handle column.
func (rs *resultsStabilizer) extractHandleCol(lp LogicalPlan) *expression.Column {
func (rs *resultReorder) extractHandleCol(lp LogicalPlan) *expression.Column {
switch x := lp.(type) {
case *LogicalSelection, *LogicalLimit:
handleCol := rs.extractHandleCol(lp.Children()[0])
Expand All @@ -115,6 +116,6 @@ func (rs *resultsStabilizer) extractHandleCol(lp LogicalPlan) *expression.Column
return nil
}

func (rs *resultsStabilizer) name() string {
return "stabilize_results"
func (rs *resultReorder) name() string {
return "result_reorder"
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,21 @@ import (
"github.com/pingcap/tidb/util/testutil"
)

var _ = Suite(&testRuleStabilizeResults{})
var _ = SerialSuites(&testRuleStabilizeResultsSerial{})
var _ = Suite(&testRuleReorderResults{})
var _ = SerialSuites(&testRuleReorderResultsSerial{})

type testRuleStabilizeResultsSerial struct {
type testRuleReorderResultsSerial struct {
store kv.Storage
dom *domain.Domain
}

func (s *testRuleStabilizeResultsSerial) SetUpTest(c *C) {
func (s *testRuleReorderResultsSerial) SetUpTest(c *C) {
var err error
s.store, s.dom, err = newStoreWithBootstrap()
c.Assert(err, IsNil)
}

func (s *testRuleStabilizeResultsSerial) TestPlanCache(c *C) {
func (s *testRuleReorderResultsSerial) TestPlanCache(c *C) {
tk := testkit.NewTestKit(c, s.store)
orgEnable := plannercore.PreparedPlanCacheEnabled()
defer func() {
Expand All @@ -54,7 +54,7 @@ func (s *testRuleStabilizeResultsSerial) TestPlanCache(c *C) {
c.Assert(err, IsNil)

tk.MustExec("use test")
tk.MustExec("set tidb_enable_stable_result_mode=1")
tk.MustExec("set tidb_enable_ordered_result_mode=1")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (a int primary key, b int, c int, d int, key(b))")
tk.MustExec("prepare s1 from 'select * from t where a > ? limit 10'")
Expand All @@ -65,10 +65,10 @@ func (s *testRuleStabilizeResultsSerial) TestPlanCache(c *C) {
tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1")) // plan cache is still working
}

func (s *testRuleStabilizeResultsSerial) TestSQLBinding(c *C) {
func (s *testRuleReorderResultsSerial) TestSQLBinding(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
tk.MustExec("set tidb_enable_stable_result_mode=1")
tk.MustExec("set tidb_enable_ordered_result_mode=1")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (a int primary key, b int, c int, d int, key(b))")
tk.MustQuery("explain select * from t where a > 0 limit 1").Check(testkit.Rows(
Expand All @@ -87,27 +87,27 @@ func (s *testRuleStabilizeResultsSerial) TestSQLBinding(c *C) {
" └─TableRowIDScan_15(Probe) 1.00 cop[tikv] table:t keep order:false, stats:pseudo"))
}

type testRuleStabilizeResults struct {
type testRuleReorderResults struct {
store kv.Storage
dom *domain.Domain

testData testutil.TestData
}

func (s *testRuleStabilizeResults) SetUpSuite(c *C) {
func (s *testRuleReorderResults) SetUpSuite(c *C) {
var err error
s.store, s.dom, err = newStoreWithBootstrap()
c.Assert(err, IsNil)

s.testData, err = testutil.LoadTestSuiteData("testdata", "stable_result_mode_suite")
s.testData, err = testutil.LoadTestSuiteData("testdata", "ordered_result_mode_suite")
c.Assert(err, IsNil)
}

func (s *testRuleStabilizeResults) TearDownSuite(c *C) {
func (s *testRuleReorderResults) TearDownSuite(c *C) {
c.Assert(s.testData.GenerateOutputIfNeeded(), IsNil)
}

func (s *testRuleStabilizeResults) runTestData(c *C, tk *testkit.TestKit, name string) {
func (s *testRuleReorderResults) runTestData(c *C, tk *testkit.TestKit, name string) {
var input []string
var output []struct {
Plan []string
Expand All @@ -122,61 +122,61 @@ func (s *testRuleStabilizeResults) runTestData(c *C, tk *testkit.TestKit, name s
}
}

func (s *testRuleStabilizeResults) TestStableResultMode(c *C) {
func (s *testRuleReorderResults) TestOrderedResultMode(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
tk.MustExec("set tidb_enable_stable_result_mode=1")
tk.MustExec("set tidb_enable_ordered_result_mode=1")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (a int primary key, b int, c int, d int, key(b))")
s.runTestData(c, tk, "TestStableResultMode")
s.runTestData(c, tk, "TestOrderedResultMode")
}

func (s *testRuleStabilizeResults) TestStableResultModeOnDML(c *C) {
func (s *testRuleReorderResults) TestOrderedResultModeOnDML(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
tk.MustExec("set tidb_enable_stable_result_mode=1")
tk.MustExec("set tidb_enable_ordered_result_mode=1")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (a int primary key, b int, c int, key(b))")
s.runTestData(c, tk, "TestStableResultModeOnDML")
s.runTestData(c, tk, "TestOrderedResultModeOnDML")
}

func (s *testRuleStabilizeResults) TestStableResultModeOnSubQuery(c *C) {
func (s *testRuleReorderResults) TestOrderedResultModeOnSubQuery(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
tk.MustExec("set tidb_enable_stable_result_mode=1")
tk.MustExec("set tidb_enable_ordered_result_mode=1")
tk.MustExec("drop table if exists t1")
tk.MustExec("drop table if exists t2")
tk.MustExec("create table t1 (a int primary key, b int, c int, d int, key(b))")
tk.MustExec("create table t2 (a int primary key, b int, c int, d int, key(b))")
s.runTestData(c, tk, "TestStableResultModeOnSubQuery")
s.runTestData(c, tk, "TestOrderedResultModeOnSubQuery")
}

func (s *testRuleStabilizeResults) TestStableResultModeOnJoin(c *C) {
func (s *testRuleReorderResults) TestOrderedResultModeOnJoin(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
tk.MustExec("set tidb_enable_stable_result_mode=1")
tk.MustExec("set tidb_enable_ordered_result_mode=1")
tk.MustExec("drop table if exists t1")
tk.MustExec("drop table if exists t2")
tk.MustExec("create table t1 (a int primary key, b int, c int, d int, key(b))")
tk.MustExec("create table t2 (a int primary key, b int, c int, d int, key(b))")
s.runTestData(c, tk, "TestStableResultModeOnJoin")
s.runTestData(c, tk, "TestOrderedResultModeOnJoin")
}

func (s *testRuleStabilizeResults) TestStableResultModeOnOtherOperators(c *C) {
func (s *testRuleReorderResults) TestOrderedResultModeOnOtherOperators(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
tk.MustExec("set tidb_enable_stable_result_mode=1")
tk.MustExec("set tidb_enable_ordered_result_mode=1")
tk.MustExec("drop table if exists t1")
tk.MustExec("drop table if exists t2")
tk.MustExec("create table t1 (a int primary key, b int, c int, d int, unique key(b))")
tk.MustExec("create table t2 (a int primary key, b int, c int, d int, unique key(b))")
s.runTestData(c, tk, "TestStableResultModeOnOtherOperators")
s.runTestData(c, tk, "TestOrderedResultModeOnOtherOperators")
}

func (s *testRuleStabilizeResults) TestStableResultModeOnPartitionTable(c *C) {
func (s *testRuleReorderResults) TestOrderedResultModeOnPartitionTable(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
tk.MustExec("set tidb_enable_stable_result_mode=1")
tk.MustExec("set tidb_enable_ordered_result_mode=1")
tk.MustExec("drop table if exists thash")
tk.MustExec("drop table if exists trange")
tk.MustExec("create table thash (a int primary key, b int, c int, d int) partition by hash(a) partitions 4")
Expand All @@ -185,5 +185,5 @@ func (s *testRuleStabilizeResults) TestStableResultModeOnPartitionTable(c *C) {
partition p1 values less than (200),
partition p2 values less than (300),
partition p3 values less than (400))`)
s.runTestData(c, tk, "TestStableResultModeOnPartitionTable")
s.runTestData(c, tk, "TestOrderedResultModeOnPartitionTable")
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[
{
"name": "TestStableResultMode",
"name": "TestOrderedResultMode",
"cases": [
"select * from t use index(primary)",
"select b from t use index(b)",
Expand All @@ -19,7 +19,7 @@
]
},
{
"name": "TestStableResultModeOnDML",
"name": "TestOrderedResultModeOnDML",
"cases": [
"insert into t select * from t",
"insert into t select * from t where a>1",
Expand All @@ -32,7 +32,7 @@
]
},
{
"name": "TestStableResultModeOnSubQuery",
"name": "TestOrderedResultModeOnSubQuery",
"cases": [
"select * from t1 where t1.a in (select b from t2)",
"select * from t1 where t1.a not in (select b from t2)",
Expand All @@ -46,7 +46,7 @@
]
},
{
"name": "TestStableResultModeOnJoin",
"name": "TestOrderedResultModeOnJoin",
"cases": [
"select * from t1, t2 where t1.a = t2.a",
"select * from t1, t2 where t1.a > t2.a and t1.b = t2.b and t1.c < t2.c",
Expand All @@ -55,7 +55,7 @@
]
},
{
"name": "TestStableResultModeOnOtherOperators",
"name": "TestOrderedResultModeOnOtherOperators",
"cases": [
"select * from t1 where a = 1 or a = 222 or a = 33333",
"select * from t1 where a in (1, 2, 3, 4)",
Expand All @@ -70,7 +70,7 @@
]
},
{
"name": "TestStableResultModeOnPartitionTable",
"name": "TestOrderedResultModeOnPartitionTable",
"cases": [
"select * from thash where a in (1, 200)",
"select * from thash where a >= 50 and a <= 150",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[
{
"Name": "TestStableResultMode",
"Name": "TestOrderedResultMode",
"Cases": [
{
"Plan": [
Expand Down Expand Up @@ -113,7 +113,7 @@
]
},
{
"Name": "TestStableResultModeOnDML",
"Name": "TestOrderedResultModeOnDML",
"Cases": [
{
"Plan": [
Expand Down Expand Up @@ -179,7 +179,7 @@
]
},
{
"Name": "TestStableResultModeOnSubQuery",
"Name": "TestOrderedResultModeOnSubQuery",
"Cases": [
{
"Plan": [
Expand Down Expand Up @@ -283,7 +283,7 @@
]
},
{
"Name": "TestStableResultModeOnJoin",
"Name": "TestOrderedResultModeOnJoin",
"Cases": [
{
"Plan": [
Expand Down Expand Up @@ -330,7 +330,7 @@
]
},
{
"Name": "TestStableResultModeOnOtherOperators",
"Name": "TestOrderedResultModeOnOtherOperators",
"Cases": [
{
"Plan": [
Expand Down Expand Up @@ -414,7 +414,7 @@
]
},
{
"Name": "TestStableResultModeOnPartitionTable",
"Name": "TestOrderedResultModeOnPartitionTable",
"Cases": [
{
"Plan": [
Expand Down
2 changes: 1 addition & 1 deletion session/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -2228,7 +2228,7 @@ var builtinGlobalVariable = []string{
variable.TiDBEnableRateLimitAction,
variable.TiDBMemoryUsageAlarmRatio,
variable.TiDBMultiStatementMode,
variable.TiDBEnableStableResultMode,
variable.TiDBEnableOrderedResultMode,
}

var (
Expand Down
Loading