Skip to content

Commit

Permalink
planner: rename stable-result-mode to ordered-result-mode (#26093) (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
ti-srebot authored Jul 27, 2021
1 parent 48c4b91 commit 95f9a39
Show file tree
Hide file tree
Showing 10 changed files with 74 additions and 73 deletions.
18 changes: 9 additions & 9 deletions executor/set_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -548,15 +548,15 @@ func (s *testSerialSuite1) TestSetVar(c *C) {
tk.MustExec("set @@tidb_enable_clustered_index = 'int_only'")
tk.MustQuery(`show warnings`).Check(testkit.Rows("Warning 1287 'INT_ONLY' is deprecated and will be removed in a future release. Please use 'ON' or 'OFF' instead"))

// 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 @@ -65,7 +65,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_16(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 @@ -331,7 +331,7 @@
]
},
{
"Name": "TestStableResultModeOnOtherOperators",
"Name": "TestOrderedResultModeOnOtherOperators",
"Cases": [
{
"Plan": [
Expand Down Expand Up @@ -415,7 +415,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 @@ -2546,7 +2546,7 @@ var builtinGlobalVariable = []string{
variable.TiDBMultiStatementMode,
variable.TiDBEnableExchangePartition,
variable.TiDBAllowFallbackToTiKV,
variable.TiDBEnableStableResultMode,
variable.TiDBEnableOrderedResultMode,
}

// loadCommonGlobalVariablesIfNeeded loads and applies commonly used global variables for the session.
Expand Down
Loading

0 comments on commit 95f9a39

Please sign in to comment.