[BUG] tispark 3.x版本读取tikv时,读取并发比2.5版本少,速度也慢

【 TiDB 使用环境】生产环境
【 TiDB 版本】v5.4.2
【遇到的问题】spark version: 3.x (spark 3的任意版本), tispark version : 3.x (tispark 3的任意版本)
【问题现象及影响】

table 信息:

spark 配置:

tispark 2.5版本:

tispark3.x版本:

代码完全相同,只是换了tispark版本。

麻烦确认以下信息:

  1. 是同一个 Query 下,并发少,速度变慢么?‘
  2. 确认一下表的统计信息和对应的 SQL 在 Tispark 的执行计划是否有差异?
  3. 确认一下对应的表的数据量是否有更替,最好的对比方法就是同时挂在两个版本的 Tispark 启动以后,分别执行相同的 SQL 对一下执行计划好和延迟情况,这块是否做过测试?

1.是的,完全相同,除了tispark版本不同。
2.只是简单的select *.
3.表没有任何变动,我就是这样测试的。

提供一下执行计划?

CREATE TABLE `perio_art_project` (
  `record_id` int(11) DEFAULT NULL,
  `article_id` varchar(255) DEFAULT NULL,
  `project_seq` int(11) DEFAULT NULL,
  `project_id` varchar(255) DEFAULT NULL,
  `project_name` longtext DEFAULT NULL,
  `batch_id` int(11) DEFAULT NULL,
  `primary_partition` int(4) GENERATED ALWAYS AS ((crc32(`article_id`)) % 9999) STORED NOT NULL,
  `last_modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `spark_update_time` datetime DEFAULT NULL,
  KEY `article_id` (`article_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
sparkSession
  .sql(
    """select * from tidb_catalog.qk_chi.perio_art_project
      |""".stripMargin)
  .groupBy("project_name")
  .count()
  .explain()
== 2.5 Physical Plan ==
AdaptiveSparkPlan isFinalPlan=false
+- HashAggregate(keys=[project_name#7], functions=[count(1)])
   +- Exchange hashpartitioning(project_name#7, 8192), true, [id=#14]
      +- HashAggregate(keys=[project_name#7], functions=[partial_count(1)])
         +- TiKV CoprocessorRDD{[table: perio_art_project] TableScan, Columns: project_name@VARCHAR(4294967295), KeyRange: [([t\200\000\000\000\000\000\003\017_r\000\000\000\000\000\000\000\000], [t\200\000\000\000\000\000\003\017_s\000\000\000\000\000\000\000\000])], startTs: 437048830927044635} EstimatedCount:18072492
== 3.x Physical Plan ==
AdaptiveSparkPlan isFinalPlan=false
+- HashAggregate(keys=[project_name#7], functions=[specialsum(count(1)#34L, LongType, 0)])
   +- Exchange hashpartitioning(project_name#7, 8192), true, [id=#13]
      +- HashAggregate(keys=[project_name#7], functions=[partial_specialsum(count(1)#34L, LongType, 0)])
         +- TiSpark RegionTaskExec{downgradeThreshold=1000000000,downgradeFilter=[]
            +- TiKV FetchHandleRDD{[table: perio_art_project] IndexLookUp, Columns: project_name@VARCHAR(4294967295): { {IndexRangeScan(Index:article_id(article_id)): { RangeFilter: [], Range: [([t\200\000\000\000\000\000\003\017_i\200\000\000\000\000\000\000\001\000], [t\200\000\000\000\000\000\003\017_i\200\000\000\000\000\000\000\001\372])] }}; {TableRowIDScan, Aggregates: Count(1), First(project_name@VARCHAR(4294967295)), Group By: [project_name@VARCHAR(4294967295) ASC]} }, startTs: 437048801724203020}

这个执行计划应该是有问题的,明显没有用到索引,怎么会走索引呢。这是tidb的执行计划:

|Projection_4|3462592.98|root||qk_chi.perio_art_project.project_name, Column#11|
|---|---|---|---|---|
|└─HashAgg_9|3462592.98|root||group by:qk_chi.perio_art_project.project_name, funcs:count(Column#12)->Column#11, funcs:firstrow(qk_chi.perio_art_project.project_name)->qk_chi.perio_art_project.project_name|
|  └─TableReader_10|3462592.98|root||data:HashAgg_5|
|    └─HashAgg_5|3462592.98|cop[tikv]||group by:qk_chi.perio_art_project.project_name, funcs:count(1)->Column#12|
|      └─TableFullScan_8|18072492.00|cop[tikv]|table:perio_art_project|keep order:false|

找到原因了,是因为新版本中,没有调用StatisticsManager.loadStatisticsInfo对statisticsMap进行初始化,导致在TiStrategy.filterToDAGRequest时通过StatisticsManager.getTableStatistics获取统计信息为null,进而导致TiKVScanAnalyzer.buildIndexScan时不能正确的返回calculateCostAndEstimateCount。