Skip to content

Commit

Permalink
planner: fix unique key get wrong row count when to query the NULL va…
Browse files Browse the repository at this point in the history
…lue (#56154)

close #56116
  • Loading branch information
ti-chi-bot authored Sep 22, 2024
1 parent af46a3f commit 4261bf4
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 2 deletions.
11 changes: 9 additions & 2 deletions pkg/planner/cardinality/row_count_index.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,9 +250,16 @@ func getIndexRowCountForStatsV2(sctx context.PlanContext, idx *statistics.Index,
if fullLen {
// At most 1 in this case.
if idx.Info.Unique {
totalCount++
if !indexRange.IsOnlyNull() {
totalCount++
if debugTrace {
debugTraceEndEstimateRange(sctx, 1, debugTraceUniquePoint)
}
continue
}
totalCount = max(1, float64(idx.NullCount))
if debugTrace {
debugTraceEndEstimateRange(sctx, 1, debugTraceUniquePoint)
debugTraceEndEstimateRange(sctx, totalCount, debugTraceUniquePoint)
}
continue
}
Expand Down
1 change: 1 addition & 0 deletions pkg/planner/core/casetest/index/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ go_test(
],
data = glob(["testdata/**"]),
flaky = True,
shard_count = 3,
deps = [
"//pkg/testkit",
"//pkg/testkit/testdata",
Expand Down
15 changes: 15 additions & 0 deletions pkg/planner/core/casetest/index/index_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,18 @@ func TestInvisibleIndex(t *testing.T) {
`IndexReader_7 10000.00 root index:IndexFullScan_6`,
`└─IndexFullScan_6 10000.00 cop[tikv] table:t1, index:a(a) keep order:false, stats:pseudo`))
}

func TestOrderedIndexWithIsNull(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
// https://github.com/pingcap/tidb/issues/56116
tk.MustExec("create table t2(id bigint(20) DEFAULT NULL, UNIQUE KEY index_on_id (id))")
tk.MustExec("insert into t2 values (), (), ()")
tk.MustExec("analyze table t2")
tk.MustQuery("explain select count(*) from t2 where id is null;").Check(testkit.Rows(
"StreamAgg_17 1.00 root funcs:count(Column#5)->Column#3",
"└─IndexReader_18 1.00 root index:StreamAgg_9",
" └─StreamAgg_9 1.00 cop[tikv] funcs:count(1)->Column#5",
" └─IndexRangeScan_16 3.00 cop[tikv] table:t2, index:index_on_id(id) range:[NULL,NULL], keep order:false"))
}
12 changes: 12 additions & 0 deletions pkg/util/ranger/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,18 @@ func (ran *Range) isPoint(tc types.Context, regardNullAsPoint bool) bool {
return !ran.LowExclude && !ran.HighExclude
}

// IsOnlyNull checks if the range has [NULL, NULL] or [NULL NULL, NULL NULL] range.
func (ran *Range) IsOnlyNull() bool {
for i := range ran.LowVal {
a := ran.LowVal[i]
b := ran.HighVal[i]
if !(a.IsNull() && b.IsNull()) {
return false
}
}
return true
}

// IsPointNonNullable returns if the range is a point without NULL.
func (ran *Range) IsPointNonNullable(tc types.Context) bool {
return ran.isPoint(tc, false)
Expand Down

0 comments on commit 4261bf4

Please sign in to comment.