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 (#56117)

close #56116
  • Loading branch information
hawkingrei committed Sep 19, 2024
1 parent d99d445 commit 70a26f8
Show file tree
Hide file tree
Showing 3 changed files with 30 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 @@ -251,9 +251,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 = float64(idx.NullCount)
if debugTrace {
debugTraceEndEstimateRange(sctx, 1, debugTraceUniquePoint)
debugTraceEndEstimateRange(sctx, float64(idx.NullCount), debugTraceUniquePoint)
}
continue
}
Expand Down
9 changes: 9 additions & 0 deletions pkg/planner/core/casetest/index/index_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,4 +220,13 @@ func TestOrderedIndexWithIsNull(t *testing.T) {
"└─IndexReader_12 10.00 root index:IndexRangeScan_11",
" └─IndexRangeScan_11 10.00 cop[tikv] table:t1, index:b(b, c) range:[NULL,NULL], keep order:true, stats:pseudo",
))
// 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 @@ -142,6 +142,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 70a26f8

Please sign in to comment.