Skip to content

Commit 36e3978

Browse files
Planner: Single col out of range use original type (pingcap#55600)
ref pingcap#50080
1 parent bd68ce1 commit 36e3978

File tree

5 files changed

+84
-17
lines changed

5 files changed

+84
-17
lines changed

pkg/planner/cardinality/row_count_index.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -345,16 +345,23 @@ func getIndexRowCountForStatsV2(sctx planctx.PlanContext, idx *statistics.Index,
345345
histNDV := idx.NDV
346346
// Exclude the TopN in Stats Version 2
347347
if idx.StatsVer == statistics.Version2 {
348-
c := coll.GetCol(idx.Histogram.ID)
349-
// If this is single column of a multi-column index - use the column's NDV rather than index NDV
348+
colIDs := coll.Idx2ColUniqueIDs[idx.Histogram.ID]
349+
// Retrieve column statistics for the 1st index column
350+
c := coll.GetCol(colIDs[0])
351+
// If this is single column predicate - use the column's information rather than index.
352+
// Index histograms are converted to string. Column uses original type - which can be more accurate for out of range
350353
isSingleColRange := len(indexRange.LowVal) == len(indexRange.HighVal) && len(indexRange.LowVal) == 1
351-
if isSingleColRange && !isSingleColIdx && c != nil && c.Histogram.NDV > 0 {
354+
if isSingleColRange && c != nil && c.Histogram.NDV > 0 {
352355
histNDV = c.Histogram.NDV - int64(c.TopN.Num())
356+
count += c.Histogram.OutOfRangeRowCount(sctx, &indexRange.LowVal[0], &indexRange.HighVal[0], realtimeRowCount, modifyCount, histNDV)
353357
} else {
358+
// TODO: Extend original datatype out-of-range estimation to multi-column
354359
histNDV -= int64(idx.TopN.Num())
360+
count += idx.Histogram.OutOfRangeRowCount(sctx, &l, &r, realtimeRowCount, modifyCount, histNDV)
355361
}
362+
} else {
363+
count += idx.Histogram.OutOfRangeRowCount(sctx, &l, &r, realtimeRowCount, modifyCount, histNDV)
356364
}
357-
count += idx.Histogram.OutOfRangeRowCount(sctx, &l, &r, realtimeRowCount, modifyCount, histNDV)
358365
}
359366

360367
if debugTrace {

pkg/planner/cardinality/testdata/cardinality_suite_out.json

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
{
2525
"Start": 800,
2626
"End": 900,
27-
"Count": 767.004166655054
27+
"Count": 782.754166655054
2828
},
2929
{
3030
"Start": 900,
@@ -79,7 +79,7 @@
7979
{
8080
"Start": 800,
8181
"End": 1000,
82-
"Count": 1225.196869573942
82+
"Count": 1240.946869573942
8383
},
8484
{
8585
"Start": 900,
@@ -104,7 +104,7 @@
104104
{
105105
"Start": 200,
106106
"End": 400,
107-
"Count": 1231.5288209899081
107+
"Count": 1182.0288209899081
108108
},
109109
{
110110
"Start": 200,
@@ -3963,25 +3963,25 @@
39633963
{
39643964
"github.com/pingcap/tidb/pkg/statistics.(*Histogram).OutOfRangeRowCount": [
39653965
{
3966-
"lDatum": "KindBytes \\x01",
3966+
"lDatum": "KindMinNotNull <nil>",
39673967
"modifyCount": 100,
3968-
"rDatum": "KindBytes \\x03\\x7f\\xff\\xff\\xff\\xff\\xff\\xfa$",
3968+
"rDatum": "KindInt64 -1500",
39693969
"realtimeRowCount": 3080
39703970
},
39713971
{
39723972
"commonPrefix": 0,
3973-
"lScalar": 72057594037927940,
3974-
"rScalar": 252201579132747780,
3973+
"lScalar": -1.7976931348623157e+308,
3974+
"rScalar": -1500,
39753975
"unsigned": false
39763976
},
39773977
{
3978-
"boundL": 252201579132747780,
3979-
"boundR": 252201579132747780,
3980-
"histL": 252201579132747780,
3981-
"histR": 252201579132747780,
3982-
"lPercent": 0,
3978+
"boundL": -2997,
3979+
"boundR": 2997,
3980+
"histL": -999,
3981+
"histR": 999,
3982+
"lPercent": 0.5613744375005636,
39833983
"rPercent": 0,
3984-
"rowCount": 392.8571428571429
3984+
"rowCount": 555.760693125558
39853985
},
39863986
{
39873987
"Result": 100

tests/integrationtest/r/explain_complex.result

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,3 +291,36 @@ AAA BBB Aamt Bamt IFNULL(Tab_C.amt, 0)
291291
A01 B01 111.00 22.00 22.00
292292
A02 B02 111.00 NULL 0.00
293293
set @@sql_mode=default;
294+
use test;
295+
drop table if exists test;
296+
CREATE TABLE `test` (
297+
`ecif_party_no` varchar(20) DEFAULT NULL,
298+
`busi_cust_no` varchar(20) DEFAULT NULL,
299+
`busi_series_cd` varchar(2) DEFAULT NULL,
300+
`org_belong` varchar(15) DEFAULT NULL,
301+
`party_no` varchar(20) DEFAULT NULL,
302+
`rela_status_cd` varchar(2) DEFAULT NULL,
303+
`rela_status_desc` varchar(20) DEFAULT NULL,
304+
`created_by` varchar(100) DEFAULT 'ecifdata',
305+
`created_date` datetime DEFAULT CURRENT_TIMESTAMP,
306+
`updated_by` varchar(100) DEFAULT 'ecifdata',
307+
`updated_date` datetime DEFAULT CURRENT_TIMESTAMP,
308+
`id_tp00_cust_no_rela` varchar(40) NOT NULL DEFAULT uuid(),
309+
KEY `IX_CUST_RELA_DATE` (`updated_date`),
310+
KEY `IX_TPCNR_BCN` (`busi_cust_no`),
311+
KEY `IX_TPCNR_EPN` (`ecif_party_no`),
312+
KEY `IX_TPCNR_PAN` (`party_no`),
313+
PRIMARY KEY (`id_tp00_cust_no_rela`) /*T![clustered_index] NONCLUSTERED */
314+
);
315+
analyze table test all columns;
316+
load stats 's/issue_50080.json';
317+
explain format='brief' select * from test where updated_date > '2023-12-31 23:50:00' and updated_date < '2023-12-31 23:59:59';
318+
id estRows task access object operator info
319+
IndexLookUp 2230.84 root
320+
├─IndexRangeScan(Build) 2230.84 cop[tikv] table:test, index:IX_CUST_RELA_DATE(updated_date) range:(2023-12-31 23:50:00,2023-12-31 23:59:59), keep order:false
321+
└─TableRowIDScan(Probe) 2230.84 cop[tikv] table:test keep order:false
322+
explain format='brief' select * from test where updated_date > '2023-12-31 23:50:00' and updated_date < '2024-01-01 00:00:00';
323+
id estRows task access object operator info
324+
IndexLookUp 2234.56 root
325+
├─IndexRangeScan(Build) 2234.56 cop[tikv] table:test, index:IX_CUST_RELA_DATE(updated_date) range:(2023-12-31 23:50:00,2024-01-01 00:00:00), keep order:false
326+
└─TableRowIDScan(Probe) 2234.56 cop[tikv] table:test keep order:false

tests/integrationtest/s.zip

86.3 KB
Binary file not shown.

tests/integrationtest/t/explain_complex.test

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,3 +195,30 @@ explain select Tab_A.name AAA,Tab_B.name BBB,Tab_A.amt Aamt, Tab_C.amt Bamt,IFNU
195195
select Tab_A.name AAA,Tab_B.name BBB,Tab_A.amt Aamt, Tab_C.amt Bamt,IFNULL(Tab_C.amt, 0) FROM Tab_A left join Tab_B on Tab_A.bid=Tab_B.id left join Tab_C on Tab_A.cid=Tab_C.id and Tab_A.type='01' where Tab_A.num=112;
196196

197197
set @@sql_mode=default;
198+
199+
# https://github.com/pingcap/tidb/issues/50080
200+
use test;
201+
drop table if exists test;
202+
CREATE TABLE `test` (
203+
`ecif_party_no` varchar(20) DEFAULT NULL,
204+
`busi_cust_no` varchar(20) DEFAULT NULL,
205+
`busi_series_cd` varchar(2) DEFAULT NULL,
206+
`org_belong` varchar(15) DEFAULT NULL,
207+
`party_no` varchar(20) DEFAULT NULL,
208+
`rela_status_cd` varchar(2) DEFAULT NULL,
209+
`rela_status_desc` varchar(20) DEFAULT NULL,
210+
`created_by` varchar(100) DEFAULT 'ecifdata',
211+
`created_date` datetime DEFAULT CURRENT_TIMESTAMP,
212+
`updated_by` varchar(100) DEFAULT 'ecifdata',
213+
`updated_date` datetime DEFAULT CURRENT_TIMESTAMP,
214+
`id_tp00_cust_no_rela` varchar(40) NOT NULL DEFAULT uuid(),
215+
KEY `IX_CUST_RELA_DATE` (`updated_date`),
216+
KEY `IX_TPCNR_BCN` (`busi_cust_no`),
217+
KEY `IX_TPCNR_EPN` (`ecif_party_no`),
218+
KEY `IX_TPCNR_PAN` (`party_no`),
219+
PRIMARY KEY (`id_tp00_cust_no_rela`) /*T![clustered_index] NONCLUSTERED */
220+
);
221+
analyze table test all columns;
222+
load stats 's/issue_50080.json';
223+
explain format='brief' select * from test where updated_date > '2023-12-31 23:50:00' and updated_date < '2023-12-31 23:59:59';
224+
explain format='brief' select * from test where updated_date > '2023-12-31 23:50:00' and updated_date < '2024-01-01 00:00:00';

0 commit comments

Comments
 (0)