select * from table_name limit 1很慢

【 TiDB 使用环境】生产环境
【 TiDB 版本】 7.1.3
tidb执行简单的select limit 1查询,很慢,没理解其中原因,表大小大概7亿左右,理论上这种sql查询速度应该很快的,类似情况多套集群都出现过
表结构如下:
Create Table

CREATE TABLE tbl_common_sum_batch_task (
id bigint(20) NOT NULL,
create_time datetime(6) DEFAULT NULL,
last_modify_time datetime(6) DEFAULT NULL,
task_table varchar(32) DEFAULT NULL,
task_type varchar(32) DEFAULT NULL,
task_unique_key varchar(32) DEFAULT NULL,
sum_batch_result text DEFAULT NULL,
status varchar(32) DEFAULT NULL,
PRIMARY KEY (id) /*T![clustered_index] CLUSTERED */,
KEY idx_tcst_ct (create_time),
KEY idx_tcst_tt (task_type),
KEY idx_tcst_tuk (task_unique_key)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
执行时间如图:

你主键是是创建主键时自动创建的聚集索引吧,会不会执行计划是全表扫描

explain analyze 下看看,可能mvcc版本太多了,这个表delete和update多吗

是的,表创建的时候默认id做聚集索引!执行计划就是全表扫描,这种不带条件的limit 1,理论上是应该匹配到了,sql查询就结束,不需要全表扫描吧!

这个和表健康度有关系吗?我验证了一个其他的表,也是这种select limit 1很慢的,健康度有82,执行时间2min21s,执行计划做的是tablefullscan,这种limit 1 不应该是匹配到数据就结束吗!

id estRows actRows task access object execution info operator info memory disk
Limit_7 1.00 1 root time:46.2s, loops:2, RU:14290.225914 offset:0, count:1 N/A N/A
└─TableReader_11 1.00 1 root time:46.2s, loops:1, cop_task: {num: 3272, max: 0s, min: 0s, avg: 14ms, p95: 63.8ms, tot_proc: 40.4s, tot_wait: 2.31s, rpc_num: 3272, rpc_time: 45.8s, copr_cache_hit_ratio: 0.39, build_task_duration: 129.6ms, max_distsql_concurrency: 1} data:Limit_10 2.56 KB N/A
└─Limit_10 1.00 1 cop[tikv] tikv_task:{proc max:260ms, min:0s, avg: 34ms, p80:58.5ms, p95:96ms, iters:3272, tasks:3272}, scan_detail: {total_keys: 85992822, get_snapshot_time: 2.13s, rocksdb: {delete_skipped_count: 7041559, key_skipped_count: 93032399, block: {cache_hit_count: 139232, read_count: 1329, read_byte: 6.82 MB, read_time: 6.49ms}}} offset:0, count:1 N/A N/A
└─TableFullScan_9 1.00 1 cop[tikv] table:TBL_NC_PAY_ORDER tikv_task:{proc max:260ms, min:0s, avg: 34ms, p80:58.5ms, p95:96ms, iters:3272, tasks:3272} keep order:false N/A N/A

是匹配到数据就结束了,你看actrows都是1

tot_proc: 40.4s,
你TIKV有什么瓶颈么?
cop_task 的总处理时间怎么这么长?

tikv我看监控负载什么的都不高,应该不存在性能问题!

rocksdb: {delete_skipped_count: 7041559, key_skipped_count: 93032399
tikv 3000多个 rpc消耗了40s

有太多被删掉的数据了,limit 1 就会导致并发的 rpc 只有一个,然后一个一个 region 去读,但的读到的 region 数据都被删掉了,就会一个个找下去,每个 rpc 的耗时几十毫秒,总体耗时就高了。

感谢感谢,针对这种问题需要怎么解决呢?analyze table是否可行?gc操作不是应该会清除历史版本,我这里默认的10min!

感谢感谢,针对这种问题需要怎么解决呢?analyze table是否可行?gc操作不是应该会清除历史版本,我这里默认的10min!

避免走全表扫描,给个where条件走索引

gc了没用,还得compact之后才会扫不到
在使用 Compaction Filter 机制时,可能会出现 GC 进度延迟的情况,从而影响 TiKV 扫描性能。当你的负载中含有大量 coprocessor 请求,并且在 TiKV-Details > Coprocessor Detail 面板中发现 Total Ops Details 的 next()prev() 调用次数远远超过 processed_keys 调用的三倍时,可以采取以下措施:

  • 对于 TiDB v7.1.3 之前版本,建议尝试关闭 Compaction Filter,以加快 GC 速度。
  • 从 v7.1.3 开始,TiDB 会根据每个 Region 的冗余版本数量 region-compact-min-redundant-rows 和比例 region-compact-redundant-rows-percent 自动触发 compaction,从而提高 Compaction Filter 的 GC 速度。因此,在 v7.1.3 及之后的版本中,如果遇到上述情况,建议调整这两个参数,无需关闭 Compaction Filter。

默认10分钟,gc是否正常执行了呢?

1.收集表的统计信息试一下
2.通过SHOW PROCESSLIST;查看当前正在运行的查询,看看是否有长时间运行的任务占用了大量资源

个别时间段会出现gc暂停的日志:
[2025/01/10 21:39:44.909 +08:00] [INFO] [gc_worker.go:731] [“[gc worker] there’s another service in the cluster requires an
earlier safe point. gc will continue with the earlier one”] [uuid=638e2c77c48000f] [ourSafePoint=455217193912107008] [minS
afePoint=455187913738027137]
[2025/01/10 21:39:44.909 +08:00] [INFO] [gc_worker.go:707] [“[gc worker] last safe point is later than current one.No need
to gc.This might be caused by manually enlarging gc lifetime”] [“leaderTick on”=638e2c77c48000f] [“last safe point”=2025/01
/09 14:28:09.882 +08:00] [“current safe point”=2025/01/09 14:28:09.882 +08:00]
暂时没找到到这这个gc暂停的原因

为啥要用limit 1 啊 加个条件where id=1 不行吗
limit 1 也是随机的一行

发下执行计划,看着你这主键索引没用上