Skip to content

Commit 9679858

Browse files
committed
planner: fix unique key get wrong row count when to query the NULL value (pingcap#56117)
close pingcap#56116
1 parent 1a0c3ac commit 9679858

File tree

3 files changed

+30
-2
lines changed

3 files changed

+30
-2
lines changed

pkg/planner/cardinality/row_count_index.go

+9-2
Original file line numberDiff line numberDiff line change
@@ -250,9 +250,16 @@ func getIndexRowCountForStatsV2(sctx context.PlanContext, idx *statistics.Index,
250250
if fullLen {
251251
// At most 1 in this case.
252252
if idx.Info.Unique {
253-
totalCount++
253+
if !indexRange.IsOnlyNull() {
254+
totalCount++
255+
if debugTrace {
256+
debugTraceEndEstimateRange(sctx, 1, debugTraceUniquePoint)
257+
}
258+
continue
259+
}
260+
totalCount = float64(idx.NullCount)
254261
if debugTrace {
255-
debugTraceEndEstimateRange(sctx, 1, debugTraceUniquePoint)
262+
debugTraceEndEstimateRange(sctx, float64(idx.NullCount), debugTraceUniquePoint)
256263
}
257264
continue
258265
}

pkg/planner/core/casetest/index/index_test.go

+9
Original file line numberDiff line numberDiff line change
@@ -220,4 +220,13 @@ func TestOrderedIndexWithIsNull(t *testing.T) {
220220
"└─IndexReader_12 10.00 root index:IndexRangeScan_11",
221221
" └─IndexRangeScan_11 10.00 cop[tikv] table:t1, index:b(b, c) range:[NULL,NULL], keep order:true, stats:pseudo",
222222
))
223+
// https://github.com/pingcap/tidb/issues/56116
224+
tk.MustExec("create table t2(id bigint(20) DEFAULT NULL, UNIQUE KEY index_on_id (id))")
225+
tk.MustExec("insert into t2 values (), (), ()")
226+
tk.MustExec("analyze table t2")
227+
tk.MustQuery("explain select count(*) from t2 where id is null;").Check(testkit.Rows(
228+
"StreamAgg_17 1.00 root funcs:count(Column#5)->Column#3",
229+
"└─IndexReader_18 1.00 root index:StreamAgg_9",
230+
" └─StreamAgg_9 1.00 cop[tikv] funcs:count(1)->Column#5",
231+
" └─IndexRangeScan_16 3.00 cop[tikv] table:t2, index:index_on_id(id) range:[NULL,NULL], keep order:false"))
223232
}

pkg/util/ranger/types.go

+12
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,18 @@ func (ran *Range) isPoint(tc types.Context, regardNullAsPoint bool) bool {
142142
return !ran.LowExclude && !ran.HighExclude
143143
}
144144

145+
// IsOnlyNull checks if the range has [NULL, NULL] or [NULL NULL, NULL NULL] range.
146+
func (ran *Range) IsOnlyNull() bool {
147+
for i := range ran.LowVal {
148+
a := ran.LowVal[i]
149+
b := ran.HighVal[i]
150+
if !(a.IsNull() && b.IsNull()) {
151+
return false
152+
}
153+
}
154+
return true
155+
}
156+
145157
// IsPointNonNullable returns if the range is a point without NULL.
146158
func (ran *Range) IsPointNonNullable(tc types.Context) bool {
147159
return ran.isPoint(tc, false)

0 commit comments

Comments
 (0)