TiDB 可观测性解读(二)丨算子执行信息性能诊断案例分享

导读

可观测性已经成为分布式系统成功运行的关键组成部分。如何借助多样、全面的数据,让架构师更简单、高效地定位问题、分析问题、解决问题,已经成为业内的一个技术焦点。本系列文章将深入解读 TiDB 的关键参数,帮助大家更好地观测系统的状态,实现性能的优化提升。

本文为 TiDB 可观测性解读系列文章的第二篇,将探讨如何利用算子执行信息更准确地分析和诊断 SQL 性能。


你有没有遇到过这样的情况:同样模式的 SQL 语句,仅仅是日期参数或者函数的变化,最终返回的结果形式也都相同,性能却相差几十甚至上百倍。现实中遇到这样的问题,我们一般会运行 explain 语句,检查执行计划的变化情况。如果执行计划没有改变,如何进行进一步排查?

这种情况下,可以通过 explain analyze 语句来深入查看算子的实际运行情况。本文将结合实际案例和常见问题,探讨如何利用算子执行信息更准确地分析和诊断 SQL 性能。

算子执行信息介绍

通常我们可以用 explain analyze 语句获得算子执行信息。 explain analyze 会实际执行对应的 SQL 语句,同时记录其运行时信息,和执行计划一并返回出来,记录的信息包括: actRows 、 execution info 、 memory 、 disk 。

算子执行信息介绍

不同算子的 execution info 可以通过 TiDB 文档 ( https://docs.pingcap.com/zh/tidb/stable/sql-statement-explain-analyze )了解。这些信息是研发人员在长期的性能问题定位中,总结提炼出来的指标,值得每一个想对 TiDB SQL 性能诊断有深入研究的同学阅读。

有时候一些 SQL 的性能问题是偶发的,这会增加我们直接使用 explain analyze 来分析的难度。这时候我们还需要借助慢日志功能来获取有效的算子执行信息。通常,我们可以通过 TiDB Dashboard 的慢日志查询 ( https://docs.pingcap.com/zh/tidb/stable/dashboard-overview#最近的慢查询 )页面,快速定位并查询到问题 SQL 的详细执行信息。

案例和问题

接下来,我们将通过一些具体案例来探讨相关问题。请注意,以下案例中的执行计划大多直接来源于生产环境(做了脱敏处理),由于本地难以复现这些场景,版本难以统一。但版本差异并不影响问题诊断和分析的完整性,本文主要探讨诊断问题的思路和方法。

查询延时抖动

查询偶发性延时抖动是较为常见的性能问题之一。如果能够通过慢日志定位到导致性能抖动的具体查询语句,进一步分析这些查询的算子执行信息,往往能够找到问题的根源并获得有效的优化线索。

实际案例

以一个客户遇到过的点查询性能抖动问题为例,点查询的延迟偶尔会超过 2s。我们先通过慢日志查询,定位到某次查询的算子执行信息:

mysql> explain analyze select * from t0 where col0 = 100 and col1 = 'A';
+---------------------+---------+---------+-----------+---------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------+---------+------+
| id                  | estRows | actRows | task      | access object                               | execution info                                                                                                                                                                                                                                                                                                                                                                  | operator info | memory  | disk |
+---------------------+---------+---------+-----------+---------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------+---------------+---------+------+
| Point_Get_1         | 1       | 1       | root      | table:t0, index:uniq_col0_col1              | time:2.52s, loops:2, ResolveLock:{num_rpc:1, total_time:2.52s}, Get:{num_rpc:3, total_time:2.2ms}, txnNotFound_backoff:{num:12, total_time:2.51s}, tikv_wall_time: 322.8us, scan_detail: {total_process_keys: 2, total_process_keys_size: 825, total_keys: 9, get_snapshot_time: 18us, rocksdb: {delete_skipped_count: 3, key_skipped_count: 14, block: {cache_hit_count: 16}}} | N/A           | N/A     | N/A  |
+---------------------+---------+---------+-----------+---------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------+---------------+---------+------+
诊断分析

首先,我们看到查询中只有一个 Point_Get_1 算子,其 execution info 中记录的执行时间为 2.52s 。这说明执行时间被完整记录了下来。

进一步查看 execution info ,我们注意到其中包含 ResolveLock 项。这一项的细节显示,总的执行时间为 2.52s ,这意味着查询的绝大部分时间都花在了 resolve lock 操作上。与此同时,实际的 Get 统计项显示总时间为 2.2ms ,这表明获取数据本身几乎不耗时。

此外,还有一个 txnNotFound_backoff 项,它记录了因残留事务触发的重试信息。这里显示总共进行了 12 次重试 ,累计耗时 2.51s ,与 ResolveLock 项的 2.52s 基本一致。因此,我们可以初步推测:点查询可能读取到了残留事务的锁,尝试 resolve lock 时发现锁已过期,进而触发了锁清理操作,这一过程导致了较高的查询延迟。

接下来,我们可以通过监控数据进一步验证这一推测:
诊断分析

算子并发度

在 TiDB 中,我们可以通过设置一些系统参数来调节算子的执行并发度,从而最终调节 SQL 的执行性能。算子的执行并发度往往对 SQL 的执行性能有重要的影响,比如同样多的 cop task,我们把并发度从 5 改到 10,性能可能就会有将近 1 倍的提升,当然也会更集中地占用系统的资源。执行信息可以帮助我们了解算子的实际执行并发度,为更进一步的性能诊断做好准备。下面我们来看一个运维同学实际遇到的问题。

实际问题

系统中设置了 tidb_executor_concurrency 为 5 以控制算子的并发度;同时设置了 tidb_distsql_scan_concurrency 为 15,用于限制每个读取算子的最大线程数。那么,在下述执行计划中, cop_task 和 tikv_task 是如何与这两个参数相对应的呢?

mysql> explain analyze select * from t0 where c like '2147%';
+-------------------------------+---------+---------+-----------+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------+---------+------+
| id                            | estRows | actRows | task      | access object                 | execution info                                                                                                                                                                                                                                                                                                                                                                                                                                                        | operator info                           | memory  | disk |
+-------------------------------+---------+---------+-----------+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------+---------+------+
| IndexLookUp_10                | 3.82    | 99      | root      |                               | time:2.83ms, loops:2, index_task: {total_time: 733.8µs, fetch_handle: 727.9µs, build: 806ns, wait: 5.14µs}, table_task: {total_time: 1.96ms, num: 1, concurrency: 5}, next: {wait_index: 821µs, wait_table_lookup_build: 108.2µs, wait_table_lookup_resp: 1.85ms}                                                                                                                                                                                                     |                                         | 41.0 KB | N/A  |
| ├─IndexRangeScan_8(Build)     | 3.82    | 99      | cop[tikv] | table:t0, index:idx_c(c)      | time:719.1µs, loops:3, cop_task: {num: 1, max: 650µs, proc_keys: 99, rpc_num: 1, rpc_time: 625.7µs, copr_cache_hit_ratio: 0.00, distsql_concurrency: 15}, tikv_task:{time:0s, loops:3}, scan_detail: {total_process_keys: 99, total_process_keys_size: 18810, total_keys: 100, get_snapshot_time: 102µs, rocksdb: {key_skipped_count: 99, block: {cache_hit_count: 3}}}                                                                                               | range:["2147","2148"), keep order:false | N/A     | N/A  |
| └─TableRowIDScan_9(Probe)     | 3.82    | 99      | cop[tikv] | table:t0                      | time:1.83ms, loops:2, cop_task: {num: 4, max: 736.9µs, min: 532.6µs, avg: 599µs, p95: 736.9µs, max_proc_keys: 44, p95_proc_keys: 44, rpc_num: 4, rpc_time: 2.32ms, copr_cache_hit_ratio: 0.00, distsql_concurrency: 15}, tikv_task:{proc max:0s, min:0s, avg: 0s, p80:0s, p95:0s, iters:5, tasks:4}, scan_detail: {total_process_keys: 99, total_process_keys_size: 22176, total_keys: 99, get_snapshot_time: 217.3µs, rocksdb: {block: {cache_hit_count: 201}}}      | keep order:false                        | N/A     | N/A  |
+-------------------------------+---------+---------+-----------+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------+---------+------+
3 rows in set (0.00 sec)
问题分析

我们正好借这个例子解释下执行信息中 cop_task 和 tikv_task 项的关系以及 cop task 的实际执行并发度。

cop_task 和 tikv_task 的关系

首先需要明确, execution info 中的各类 xxx_task 和执行计划中的 “ task ” 列并不是同一个概念。

例如,在执行计划中, task 列的类别分别为“ root ” 、 “ cop[tikv] ”等。它既描述了算子实际在哪个组件执行(如 TiDB、TiKV 或 TiFlash),又进一步说明了其与存储引擎的通信协议类型(如 Coprocessor、Batch Coprocessor 或 MPP)。

相比之下, execution info 中的各类 task 更多是从不同维度对算子执行信息进行拆解,以便用户快速定位潜在性能问题,并通过不同维度的信息进行相互印证。具体来说:

  • tikv_task 描述的是某个具体 TiKV 算子的整体执行情况;
  • cop_task 描述的是整个 RPC 任务的执行情况,它包含了 tikv_ task 。例如,一个 cop_task 可能包含 tableScan + Selection 两个算子,每个算子都有自己的 tikv_task 信息来描述其执行情况;而 cop_task 则描述了整个 RPC 请求的执行信息,其时间涵盖了这两个算子的执行时间。

类似地,在 MPP 查询中, execution info 中的 tiflash_task 统计项描述了某个具体 TiFlash 算子的整体执行情况:

+------------------------------+-------------+----------+--------------+----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------+-----------+---------+
| id                           | estRows     | actRows  | task         | access object  | execution info                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | operator info                                      | memory    | disk    |
+------------------------------+-------------+----------+--------------+----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------+-----------+---------+
| HashAgg_22                   | 1.00        | 1        | root         |                | time:17ms, open:1.92ms, close:4.83µs, loops:2, RU:1832.08, partial_worker:{wall_time:15.055084ms, concurrency:5, task_num:1, tot_wait:15.017625ms, tot_exec:12.333µs, tot_time:75.203959ms, max:15.042667ms, p95:15.042667ms}, final_worker:{wall_time:15.079958ms, concurrency:5, task_num:5, tot_wait:1.414µs, tot_exec:41ns, tot_time:75.277708ms, max:15.060375ms, p95:15.060375ms}                                                                                                                                                                                                                                                 | funcs:count(Column#19)->Column#17                  | 6.23 KB   | 0 Bytes |
| └─TableReader_24             | 1.00        | 1        | root         |                | time:16.9ms, open:1.9ms, close:3.46µs, loops:2, cop_task: {num: 2, max: 0s, min: 0s, avg: 0s, p95: 0s, copr_cache_hit_ratio: 0.00}                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      | MppVersion: 3, data:ExchangeSender_23              | 673 Bytes | N/A     |
|   └─ExchangeSender_23        | 1.00        | 1        | mpp[tiflash] |                | tiflash_task:{time:13.1ms, loops:1, threads:1}, tiflash_network: {inner_zone_send_bytes: 24}                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | ExchangeType: PassThrough                          | N/A       | N/A     |
|     └─HashAgg_9              | 1.00        | 1        | mpp[tiflash] |                | tiflash_task:{time:13.1ms, loops:1, threads:1}                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | funcs:count(test.lineitem.L_RETURNFLAG)->Column#19 | N/A       | N/A     |
|       └─TableFullScan_21     | 11997996.00 | 11997996 | mpp[tiflash] | table:lineitem | tiflash_task:{time:12.8ms, loops:193, threads:12}, tiflash_scan:{mvcc_input_rows:0, mvcc_input_bytes:0, mvcc_output_rows:0, local_regions:10, remote_regions:0, tot_learner_read:0ms, region_balance:{instance_num: 1, max/min: 10/10=1.000000}, delta_rows:0, delta_bytes:0, segments:20, stale_read_regions:0, tot_build_snapshot:0ms, tot_build_bitmap:0ms, tot_build_inputstream:15ms, min_local_stream:10ms, max_local_stream:11ms, dtfile:{data_scanned_rows:11997996, data_skipped_rows:0, mvcc_scanned_rows:0, mvcc_skipped_rows:0, lm_filter_scanned_rows:0, lm_filter_skipped_rows:0, tot_rs_index_check:3ms, tot_read:53ms}} | keep order:false                                   | N/A       | N/A     |
+------------------------------+-------------+----------+--------------+----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------+-----------+---------+
cop task 的执行并发度

首先,我们来看执行计划。 IndexLookUp_10 是一个 root 算子 。我们知道, IndexLookUp 算子主要执行两个步骤:一是通过索引获取目标行的 rowid ;二是根据 rowid 读取所需的列数据。在 IndexLookUp_10 的 execution info 中, index_task 和 table_task 的细节被分别列出。显然, index_task 对应的是 IndexRangeScan_8 算子,而 table_task 对应的是 TableRowIDScan_9 算子。

从并发度的角度来看, index_task 没有显示并发信息,这意味着 IndexRangeScan_8 算子本身的并发度默认为 1 。然而, IndexRangeScan_8 的 cop_task 的 distsql_concurrency 为 15 (由 tidb_distsql_scan_concurrency 参数决定),这意味着理论上它可以并发执行 15 个 cop task 来读取数据。

对于 table_task ,其并发度为 5 (由 tidb_executor_concurrency 参数决定),表示最多可以同时运行 5 个 TableRowIDScan_9 算子 。而 TableRowIDScan_9 的 cop_task 的 distsql_concurrency 同样为 15 (由 tidb_distsql_scan_concurrency 决定)。因此, table_task 的最大并发读取能力为 5 × 15 = 75 个 cop task 。

max 换成 min,慢了好几十倍

实际案例

一条对索引列求 max 值的 SQL 花费 100 毫秒左右,换成求 min 值,却需要花费 8s 多时间,这是他们 explain analyze 的信息:

 mysql> explain analyze select max(time_a) from t0 limit 1;
+--------------------------------+---------+---------+-----------+----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+-----------+------+
| id                             | estRows | actRows | task      | access object                                      | execution info                                                                                                                            | operator info                                            | memory    | disk |
+--------------------------------+---------+---------+-----------+----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+-----------+------+
| Limit_14                       | 1.00.   | 1       | root      |                                                    | time:2.328901ms, loops:2                                                                                                                  | offset:0, count:1                                        | N/A       | N/A  |                       
| └─StreamAgg_19                 | 1.00    | 1       | root      |                                                    | time:2.328897ms, loops:1                                                                                                                  | funcs:max(t0.time_a)->Column#18                          | 128 Bytes | N/A  |
|   └─Limit_39                   | 1.00    | 1       | root      |                                                    | time:2.324137ms, loops:2                                                                                                                  | offset:0, count:1                                        | N/A       | N/A  |
|     └─IndexReader_45           | 1.00    | 1       | root      |                                                    | time:2.322215ms, loops:1, cop_task: {num: 1, max:2.231389ms, proc_keys: 32, rpc_num: 1, rpc_time: 2.221023ms, copr_cache_hit_ratio: 0.00} | index:Limit_26                                           | 461 Bytes | N/A  |
|       └─Limit_44               | 1.00    | 1       | cop[tikv] |                                                    | time:0ns, loops:0, tikv_task:{time:2ms, loops:1}                                                                                          | offset:0, count:1                                        | N/A       | N/A  |
|         └─IndexFullScan_31     | 1.00    | 32      | cop[tikv] | table:t0, index:time_a(time_a)                     | time:0ns, loops:0, tikv_task:{time:2ms, loops:1}                                                                                          | keep order:true, desc                                    | N/A       | N/A  |
+------------------------------+---------+---------+-----------+----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+-----------+------+
6 rows in set (0.12 sec)

mysql> explain analyze select min(time_a) from t0 limit 1;
+--------------------------------+---------+---------+-----------+----------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+-----------------+------+
| id                             | estRows | actRows | task      | access object                                      | execution info                                                                                                                                                                                                                                                                     | operator info                                            | memory          | disk |
+--------------------------------+---------+---------+-----------+----------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+-----------------+------+
| Limit_14                       | 1.00    | 1       | root      |                                                    | time:8.263857153s, loops:2                                                                                                                                                                                                                                                         | offset:0, count:1                                        | N/A             | N/A  |
| └─StreamAgg_19                 | 1.00    | 1       | root      |                                                    | time:8.26385598s, loops:1                                                                                                                                                                                                                                                          | funcs:min(t0.time_a)->Column#18                          | 128 Bytes       | N/A  |
|   └─Limit_39                   | 1.00    | 1       | root      |                                                    | time:8.263848289s, loops:2                                                                                                                                                                                                                                                         | offset:0, count:1                                        | N/A             | N/A  |
|     └─IndexReader_45           | 1.00    | 1       | root      |                                                    | time:8.26384652s, loops:1, cop_task: {num: 175, max: 1.955114915s, min: 737.989μs, avg: 603.631575ms, p95: 1.161411687s, max_proc_keys: 480000, p95_proc_keys: 480000, tot_proc: 1m44.809s, tot_wait: 361ms, rpc_num: 175, rpc_time: 1m45.632904647s, copr_cache_hit_ratio: 0.00}  | index:Limit_44                                           | 6.6025390625 KB | N/A  |
|       └─Limit_44               | 1.00    | 1       | cop[tikv] |                                                    | time:0ns, loops:0, tikv_task:{proc max:1.955s, min:0s, p80:784ms, p95:1.118s, iters:175, tasks:175}                                                                                                                                                                                | offset:0, count:1                                        | N/A             | N/A  |
|         └─IndexFullScan_31     | 1.00    | 32      | cop[tikv] | table:t0, index:time_a(time_a)                     | time:0ns, loops:0, tikv_task:{proc max:1.955s, min:0s, p80:784ms, p95:1.118s, iters:175, tasks:175}                                                                                                                                                                                | keep order:true                                          | N/A             | N/A  |
+--------------------------------+---------+---------+-----------+----------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+-----------------+------+
6 rows in set (8.38 sec)
诊断分析

使用算子执行信息进行性能诊断时,我们一般先从上到下看每个算子本身(即去除掉等待子算子数据的时间后)的执行时间,再去寻找对整个查询性能影响最大的算子,以下为算子执行时间的计算方法:

单子算子的算子执行时间

以下是不同类型算子的执行时间计算方法:

1. 类型为 “root” 的算子

可以直接用该算子的执行时间减去其子算子的执行时间,得到该算子本身的处理时间。

2. 类型为 “cop[tikv]” 的算子

执行信息中包含 tikv_task 统计项。可以通过以下公式估算包含等待子算子数据的执行时间:

估算执行时间 = avg × tasks / concurrency

然后,再从该时间中减去子算子的执行时间,得到该算子的实际处理时间。

3. 类型为 “mpp[tiflash]”、“cop[tiflash]” 或 “batchcop[tiflash]” 的算子

执行信息中包含 tiflash_task 统计项。通常可以用 proc max 减去子算子的 proc max ,得到该算子的处理时间。这是因为对于 TiFlash 任务,可以简单理解为同一条查询的所有 TiFlash 任务是同时开始执行的。

注意: 对于 ExchangeSender 算子,其执行时间包含了等待数据被上层 ExchangeReceiver 算子接收的时间,因此往往会大于上层 ExchangeReceiver 读取内存数据的时间。

多子算子的算子执行时间

对于包含多个子算子的复合算子,其 execution info 中通常会详细列出各个子算子的执行信息。例如,在 IndexLookUp 算子的执行信息中,会明确包含 index_task 和 table_task 的执行细节。通过分析这些子算子的执行信息,我们可以精准判断哪个子算子对整体性能的影响更大,从而更有针对性地进行优化。

在这个例子中,我们可以看出 IndexReader_45 是对性能影响最大的关键算子。对比其两次执行信息可以发现, cop task 的数量存在显著差异:在“max”场景下,仅有 1 个 cop task ;而在“min”场景下,却有 175 个 cop task 。同时, proc_keys 的数量也从 32 增加到了 480,000 。

从 “operator info” 列的标记来看,“max”场景中读取顺序为降序( keep order, desc ),即从大到小读取;而“min”场景中则是默认的升序( keep order )。由此可以推测:优化器根据聚合函数的类型,对索引的读取顺序进行了优化——在“max”场景中采用降序读取,而在“min”场景中采用升序读取。这种优化策略的初衷是尽快找到第一条满足条件的数据。

在“min”场景中,最小的 keys 附近恰好存在大量已被删除但尚未回收的 keys。因此,系统在读取过程中不得不扫描大量无用数据,直到最终找到第一条有效数据,这导致了显著的性能开销。

换个日期,查询慢了 160 倍还没跑出来

实际案例

这是另一个客户的实际案例:查询 12 月 20 日 数据的 SQL 语句仅耗时 25 分钟便完成,而查询 12 月 21 日 数据的 SQL 语句却运行了超过 40 小时仍未完成,最终只能手动终止。以下是这两条 SQL 语句及其对应的执行信息:

【12.20日】
explain analyze INSERT INTO t1 (col0, col1)
SELECT
  str_to_date('20241219', '%Y%m%d') AS col0,
  count(1)
FROM t0 WHERE
  col0 = str_to_date('20241219', '%Y%m%d')
  AND col2 = '1';
+-------------------------------------+-----------+-------------+-----------+-------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------+------+
| id                                  | task      | estRows     | actRows   | operator info                                                                                               | execution info                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    | memory   | disk |
+-------------------------------------+-----------+-------------+-----------+-------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------+------+
| Insert_1                            | root      | 0           | 0         | N/A                                                                                                         | time:25m21.1s, loops:1, prepare: 25m21.1s, insert:62.2µs, lock_keys: {time:3.28ms, region:1, keys:1, slowest_rpc: {total: 0.003s, region_id: 615664606, store: 214.194.4.93:20160, tikv_wall_time: 230.1µs}, lock_rpc:2.811716ms, rpc_count:1}                                                                                                                                                                                                                                                                                                                                                                                    | 29.2 KB  | N/A  |
| └─Projection_7                      | root      | 1           | 1         | col0 -> Column#209, Column#208                                                                              | time:25m21.1s, loops:2, Concurrency:OFF                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | 380 Bytes| N/A  |
|   └─HashAgg_16                      | root      | 1           | 1         | funcs:count(Column#215) -> Column#208                                                                       | time:25m21.1s, loops:2, partial_worker:{wall_time:25m21.069799539s, concurrency:5, task_num:82364, tot_wait:2h6m36.573780845s, tot_exec:8.745753026s, tot_time:2h6m45.348679761s, max:25m21.069763913s, p95:25m21.069763913s}, final_worker:{wall_time:25m21.069835493s, concurrency:5, task_num:5, tot_wait:2h6m45.348923309s, tot_exec:18.591µs, tot_time:2h6m45.348944905s, max:25m21.069801614s, p95:25m21.069801614s}                                                                                                                                                                                                        | 260.2 KB | N/A  |
|     └─IndexLookUp_17                | root      | 1           | 84339969  | N/A                                                                                                         | time:25m19.4s, loops:82365, index_task: {total_time: 25m20.7s, fetch_handle: 7m18.7s, build: 23.5ms, wait: 18m2s}, table_task: {total_time: 2h6m24.2s, num: 5813, concurrency: 5}, next: {wait_index: 7.63ms, wait_table_lookup_build: 5.74s, wait_table_lookup_resp: 25m10.7s}                                                                                                                                                                                                                                                                                                                                                   | 52.6 MB  | N/A  |
|       ├─IndexRangeScan_13(Build)    | cop[tikv] | 59335552.00 | 118921714 | table:t0, index:idx_index0(col0, col3, col4), range:[2024-12-19,2024-12-19], keep order:false, stats:pseudo | time:1m0.5s, loops:116574, cop_task: {num: 3457, max: 359.8ms, min: 1.13ms, avg: 51.7ms, p95: 121.5ms, max_proc_keys: 50144, p95_proc_keys: 50144, tot_proc: 1m54s, tot_wait: 373ms, rpc_num: 3458, rpc_time: 2m58.7s, copr_cache_hit_ratio: 0.00, distsql_concurrency: 15}, backoff{regionMiss: 2ms}, scan_detail: {total_process_keys: 118921714, total_process_keys_size: 14309548264, total_keys: 119003503, get_snapshot_time: 635.1ms, rocksdb: {key_skipped_count: 120441534, block: {cache_hit_count: 212755, read_count: 23658, read_byte: 538.1 MB, read_time: 179.2ms}}}                                               | N/A      | N/A  |
|       └─HashAgg_9(Probe)            | cop[tikv] | 1           | 84339969  | funcs:count(1) -> Column#215                                                                                | time:1h47m18.5s, loops:90847, cop_task: {num: 91439604, max: 4.05s, min: 450µs, avg: 2.5ms, p95: 9.62ms, max_proc_keys: 9094, p95_proc_keys: 2, tot_proc: 3m46.3s, tot_wait: 1h36m3.1s, rpc_num: 91439649, rpc_time: 61h20m32.2s, copr_cache_hit_ratio: 0.00, distsql_concurrency: 15}, backoff{regionMiss: 86ms}, scan_detail: {total_process_keys: 118921714, total_process_keys_size: 272099421438, total_keys: 353720316, get_snapshot_time: 3h23m51s, rocksdb: {delete_skipped_count: 4, key_skipped_count: 234799057, block: {cache_hit_count: 2970751374, read_count: 15457191, read_byte: 268.8 GB, read_time: 4m11.8s}}} | N/A      | N/A  |
|         └─Selection_15              | cop[tikv] | 59335.55    | 110035144 | eq(t0.col2, "1")                                                                                            | tikv_task:{proc max:321ms, min:0s, avg: 193.5µs, p80:0s, p95:0s, iters:91440577, tasks:91439604}                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | N/A      | N/A  |
|           └─TableRowIDScan_14       | cop[tikv] | 59335552.00 | 118921714 | table:t0, keep order:false, stats:pseudo                                                                    | tikv_task:{proc max:321ms, min:0s, avg: 183.3µs, p80:0s, p95:0s, iters:91440577, tasks:91439604}                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | N/A      | N/A  |
+------------------------+-----------+------------+--------------------------------------------------+------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------+------+

【12.21日】          
explain analyze INSERT INTO t1 (col0, col1)
SELECT
  str_to_date('20241220', '%Y%m%d') AS col0,
  count(1)
FROM t0 WHERE
  col0 = str_to_date('20241220', '%Y%m%d')
  AND col2 = '1';
  
+-------------------------------------+-----------+-------------+-----------+-------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------+------+
| id                                  | task      | estRows     | actRows   | operator info                                                                                               | execution info                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | memory   | disk |
+-------------------------------------+-----------+-------------+-----------+-------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------+------+
| Insert_1                            | root      | 0           | 0         | N/A                                                                                                         | time:40h30m50.9s, loops:1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   | 0 Bytes  | N/A  |
| └─Projection_7                      | root      | 1           | 0         | col0 -> Column#209, Column#208                                                                              | time:40h30m50.9s, loops:1, Concurrency:OFF                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | 8.24 KB  | N/A  |
|   └─HashAgg_16                      | root      | 1           | 0         | funcs:count(Column#215) -> Column#208                                                                       | time:40h30m50.9s, loops:1, partial_worker:{wall_time:40h30m50.867278633s, concurrency:5, task_num:141733, tot_wait:202h33m46.814913611s, tot_exec:27.470849055s, tot_time:202h34m14.336192096s, max:40h30m50.867251785s, p95:40h30m50.867251785s}, final_worker:{wall_time:40h30m50.867835193s, concurrency:5, task_num:5, tot_wait:202h34m14.336323864s, tot_exec:587.154µs, tot_time:202h34m14.336916359s, max:40h30m50.867823183s, p95:40h30m50.867823183s}                                                                                                                                                                                                                                                                                              | 253.9 KB | N/A  |
|     └─IndexLookUp_17                | root      | 1           | 145134747 | N/A                                                                                                         | time:40h30m44.5s, loops:141734, index_task: {total_time: 40h30m50.8s, fetch_handle: 1h26m6.1s, build: 53.4ms, wait: 39h4m44.7s}, table_task: {total_time: 202h30m18s, num: 10576, concurrency: 5}, next: {wait_index: 38.7ms, wait_table_lookup_build: 16m5.5s, wait_table_lookup_resp: 35h58m38.1s}                                                                                                                                                                                                                                                                                                                                                                                                                                                        | 54.1 MB  | N/A  |
|       ├─IndexRangeScan_13(Build)    | cop[tikv] | 59418221.51 | 216452387 | table:t0, index:idx_index0(col0, col3, col4), range:[2024-12-20,2024-12-20], keep order:false, stats:pseudo | time:1h10m20.7s, loops:212130, cop_task: {num: 6031, max: 4.3s, min: 1.25ms, avg: 68.2ms, p95: 157.5ms, max_proc_keys: 50144, p95_proc_keys: 50144, tot_proc: 4m2.6s, tot_wait: 1.72s, rpc_num: 6032, rpc_time: 6m51.3s, copr_cache_hit_ratio: 0.00, distsql_concurrency: 15}, backoff{regionMiss: 4.01s}, tikv_task:{proc max:240ms, min:0s, avg: 35ms, p80:52ms, p95:60ms, iters:235427, tasks:6031}, scan_detail: {total_process_keys: 216452387, total_process_keys_size: 26106920846, total_keys: 216513446, get_snapshot_time: 1.82s, rocksdb: {key_skipped_count: 217250001, block: {cache_hit_count: 85194, read_count: 336650, read_byte: 5.71 GB, read_time: 2.59s}}}                                                                             | N/A      | N/A  |
|       └─HashAgg_9(Probe)            | cop[tikv] | 1           | 145183684 | funcs:count(1) -> Column#215                                                                                | time:200h6m9.4s, loops:157469, cop_task: {num: 152652462, max: 5.48s, min: 428.9µs, avg: 3.46ms, p95: 9.78ms, max_proc_keys: 9041, p95_proc_keys: 3, tot_proc: 3h59m54.1s, tot_wait: 9h5m23.6s, rpc_num: 152657420, rpc_time: 138h15m0.2s, copr_cache_hit_ratio: 0.00, distsql_concurrency: 15}, backoff{regionMiss: 5.94s}, tikv_task:{proc max:468ms, min:0s, avg: 494.8µs, p80:0s, p95:4ms, iters:152653501, tasks:152652462}, scan_detail: {total_process_keys: 216364520, total_process_keys_size: 340485612010, total_keys: 490792535, get_snapshot_time: 12h12m26.1s, rocksdb: {delete_skipped_count: 1944, key_skipped_count: 274430096, block: {cache_hit_count: 5855418083, read_count: 285117868, read_byte: 4977.3 GB, read_time: 4h18m23.9s}}} | N/A      | N/A  |
|         └─Selection_15              | cop[tikv] | 59418.22    | 207051411 | eq(t0.col2, "1")                                                                                            | tikv_task:{proc max:1.3s, min:0s, avg: 489.8µs, p80:0s, p95:4ms, iters:152653501, tasks:152652462}                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | N/A      | N/A  |
|           └─TableRowIDScan_14       | cop[tikv] | 59418221.51 | 232766720 | table:t0, keep order:false, stats:pseudo                                                                    | tikv_task:{proc max:1.3s, min:0s, avg: 478.8µs, p80:0s, p95:4ms, iters:152653501, tasks:152652462}                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | N/A      | N/A  |
+------------------------+-----------+------------+--------------------------------------------------+------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------+------+
诊断分析

首先对比两次查询的执行计划,确认执行计划未发生跳变。接着,我们从上至下逐一分析,找出两次查询中主要执行时间差异的来源。可以看到, Insert_1 、 Projection_7 和 HashAgg_16 的执行时间均在秒级,因此可以排除这些算子的嫌疑。

重点聚焦于 IndexLookUp 算子。在 12 月 21 日的查询中, index_task 的总耗时为 40 小时,但实际获取 rowid 的时间仅为 1 个多小时,其余时间主要消耗在等待 table_task 读取表数据上,具体为 wait :39h4m44.7s。

进一步查看 table_task 的执行细节,以下两个信息值得关注: total_time :202h30m18s 和 concurrency :5。计算可得,平均每个并发任务的耗时为 202h / 5 = 40.4h ,与 IndexLookUp 的 总耗时基本一致。因此,基本可以确定问题出在 table_task 上,即对应的 HashAgg_9 算子。

在 HashAgg_9 算子的 execution info 中,主要包含以下关键信息:

  • time: 200h6m9.4s, loops: 157469 :该算子的任务类型为 “cop[tikv]” ,表明其实际在 TiKV 上执行。这里的执行时间反映了 TiDB 等待和读取 Coprocessor 任务返回数据的总耗时。需要注意的是,这个时间并不是实际的 walltime ,而是多个并发任务的执行时间累加而成。由于 table_task 的并发度为 5 ,因此实际算子的 walltime 大约为 200h / 5 = 40h ,与总耗时一致。从 TiDB 9.0 版本开始,我们将这种并发执行时间的统计项名称改为 to tal_t ime ,以便与真正的 walltime 区分开来。
  • cop_task : 此部分信息描述了向 TiKV 发送 cop task 的执行情况。其中, rpc_time 和 distsql_concurrency 是两个关键指标:
    • rpc_time 是 TiDB 端记录的从发送 cop task 到接收结果的总耗时。
    • distsql_concurrency 是单个 table_task 发送 cop_task 的并发度。由于 table_task 的并发度为 5 ,因此整体的 cop task 并发度为 5 × 15 = 75 。

根据这两个指标,我们可以推算出 cop task 的实际 walltime 大约为 138h / 75 ≈ 1.8h,与整体的 40h 相比,占比并不高。

  • backoff :这部分描述了 cop task 发送失败时重试的时间。
  • tikv_task :这部分是描述的 HashAgg_9 这个算子在 TiKV 上的执行信息,实际时间并不多。
  • sc an_detail :描述了 TiKV 从 RocksDB 读取数据的信息统计,由于 tikv_task 推算出算子总执行时间并不长,所以这部分信息不影响总体性能。

综合上述信息可以发现, HashAgg_9 的总执行时间并非主要消耗在 cop task 的执行上,而更可能是花费在从 cop task response 中读取数据的过程中。结合 CPU profiling 的结果,可以看到 Go runtime 的 GC(垃圾回收)占用了大约 80% 的 CPU 时间。

Go runtime 的 GC(垃圾回收)占用了大约 80% 的 CPU 时间

进一步观察 heap profiling 的结果,可以最终确认问题根源是 issue44047 ( https://github.com/pingcap/tidb/issues/44047 ):此前,TiDB 为了精确统计 cop task 的 p90 等指标,会缓存所有 cop task 的执行信息。当 cop task 数量极为庞大时,这会导致 TiDB 内存紧张,进而频繁触发 Go 的 GC(垃圾回收),最终引发性能异常。该问题已经在 TiDB 6.5 版本中修复。

进一步观察 heap profiling 的结果

未来展望

在 TiDB 9.0 版本中,我们将进一步丰富算子执行信息,提升系统的可观测性,具体改进包括:

1. 算子执行时间的细化

在 9.0 版本中,TiDB 算子的执行信息新增了 open 和 close 时间。此前,执行信息中的 time 并未涵盖算子初始化和结束执行的时间,这可能导致执行时间显著低于实际耗时(如 issue50377 ( https://github.com/pingcap/tidb/issues/50377 ) 和 issue55957 ( https://github.com/pingcap/tidb/issues/55957 ))。在 9.0 版本中, ti me 被修正为从进入算子到离开算子的完整 wall time ,包括所有子算子的执行时间。其中:

  • open :表示算子初始化所需的时间。
  • close :表示从算子处理完所有数据到完全结束的时间。
  • time 包含了 open 和 close 的时间。

2. 并发执行时间的区分

当算子存在多并发执行时,此前的 execution info 中显示的是并发任务的 wall time 累加值,这可能导致子算子的执行时间大于父算子的执行时间(如 issue56746 ( https://github.com/pingcap/tidb/issues/56746 )),容易引起混淆。在 9.0 版本中,这些累加的时间信息(如 time 、 open 和 close )将被替换为 total_time 、 total_open 和 total_close ,以更清晰地反映并发执行的真实耗时。

3. TiFlash 执行中的等待时间信息补充

在 TiFlash 的执行信息中,新增了以下等待时间的统计:

  • minTSO_wait :记录 MPP Task 等待 TiFlash MinTSO 调度器调度的时间。
  • pipeline_breaker_wait :在 TiFlash 的 Pipeline 执行模型中,记录包含 pipeline breaker 算子的 pipeline 等待上游 pipeline 数据的时间。目前主要用于展示包含 Join 算子的 pipeline 等待哈希表构建完成的时间。
  • pipeline_queue_wait :在 TiFlash 的 Pipeline 执行模型中,记录 pipeline 在 CPU Task Thread Pool 和 IO Task Thread Pool 中的等待时间。

通过这些改进,TiDB 9.0 版本将为用户提供更全面、更准确的执行信息,帮助更好地诊断和优化查询性能。

相关推荐

TiDB × AI :DeepSeek 时代你需要什么样的数据基座

AutoFlow 是一套 GraphRAG 框架,不仅提供了类似于 LlamaIndex 的能力,而且还内置语义化的知识图谱构建和召回,以及我们在 AutoFlow 上实践得出的一系列行之有效的领先的 RAG 能力(这些接下来会介绍)。不过需要强调的是,Dify 是一个开箱即用的非常易用的界面,而 AutoFlow 虽然功能更强却则具有比较高的使用门槛,所以这两个选择其实面向了不同的群体,用户需要依据自己的实际需求进行选择。它并非传统的基于规则的优化工具,而是利用大模型的知识来优化不同类型的数据库。

TiDB_PingCAP 的博客 1417

架构师必看!现代应用架构发展趋势与数据库选型建议丨TiDB vs MySQL 专题(一)

随着业务系统数据量的增长,早起只能无奈采取分库分表方案以及架构,这不单为运维带 来了极高的复杂度,同时对业务开发也带来的极大的入侵,SQL 只能限定按照 shard key 维度进行编写,无法任意维度的进行 SQL 查询,开发不得不牺牲业务需求,业务的发展也不得不受限,同时又需投入大量的高精尖人才进行开发维护。这对数据库的承载能力提出了极高的挑战,不但需要承载大数据量,又需要保障业务读写性能的稳定性,而在数据的承载能力上,MySQL 的极限,是 TiDB 的起点。一行命令完成扩展,无需任何的人工干预。

TiDB_PingCAP 的博客 1233

TiDB 观测性解读(一)丨索引观测:快速识别无用索引与低效索

通过识别并优化未使用或低效的索引,可以减少资源浪费,并提高系统的响应速度和稳定性。在 TiDB 中,TIDB_INDEX_USAGE 系统表提供了相对丰富的索引使用统计数据,帮助 DBA 快速发现低效索引,并通过优化或删除它们来提升数据库效率。尽管删除索引的操作相对简单,但在实施时仍需注意潜在的限制和风险,尤其是在大数据量和高并发环境下。定期检查索引使用情况,尤其是对于大规模数据库。确保用于决策的统计数据涵盖足够长的业务周期,避免误判。

TiDB_PingCAP 的博客 974

海量数据融合互通丨TiDB 在安徽省住房公积金监管服务平台的应用实践

目前安徽省住房公积金监管服务平台已具备一系列功能模块,包括首页、运营分析、统计报表、智慧大屏、数据治理、风险检查和系统管理。其中,运营分析主要用于从不同维度分析公积金业务指标,统计报表则负责生成、填报和查询住建部规定的报表,同时也支持省级用户的报表导入、核对和更新。智慧大屏提供了综合和业务两大类可视化展示,而数据治理模块则涵盖了传数统计、数据检核和人工数据核对等功能,以确保数据的质量。风险检查方面,平台不仅支持公积金中心的自我检查,也支持省厅的检查,并可以根据需要添加新的检查模型。

TiDB_PingCAP 的博客 1133

TiDB 2024 年度报告:增长的故事

TiDB 2024 年度报告:增长的故事

TiDB_PingCAP 的博客 329

TiDB Chat2Query 深度解析:我们如何打造一款更高效、准确的智能 SQL 生成工具?

上个季度的销售额是多少?“哪个产品类别表现最佳?“本月客户投诉的趋势如何?相比其他工具,Chat2Query 能够对用户上传的大规模数据集进行理解和分析, 摒弃繁杂的专业术语和查询语句,Chat2Query 使得用户能够通过自然语言直接向数据库提问,并即时获得答案。

TiDB_PingCAP 的博客 1335

4.98 亿月活背后的国产数据库:咪咕视讯携手 TiDB 攻克内容分发核心系统挑战

咪咕大概是 2018 年左右正式开始对分布式数据库进行研究的,到现在为止我们看到和测试过太多的国内产品。但是在当时,敢用 LSM 树而不是 B+ 树做存储引擎,敢做分布式存算引擎分离的,能够行列副本共存、优化器路由分流做 MPP shuffle 的,市面上真的真的非常非常地不多见。比较多的是精致的分库分表外挂,或某些知名国外产品的模仿版。TiDB 的产品给我的印象是极具冲击性的,那么大胆、不随大流。验证和使用下来,效果也是切实的。

TiDB_PingCAP 的博客 1208

53 倍性能提升!TiDB 全局索引如何优化分区表查询?

在 TiDB 中,全局索引是一种定义在分区表上的索引类型,它允许索引分区与表分区之间建立一对多的映射关系,即一个索引分区可以对应多个表分区。这与 TiDB 早期版本中的本地索引(Local Index)不同,本地索引的索引分区与表分区之间是一对一的映射关系,即一个分区对应一个局部的索引块。全局索引能覆盖整个表的数据,使得主键和唯一键在不包含分区键的情况下仍能保持全局唯一性。此外,全局索引可以在一次操作中访问多个分区的索引数据,而无需对每个分区的本地索引逐一查找,显著提升了针对非分区键的查询性能。

TiDB_PingCAP 的博客 1356

一行代码不用写,用 Autoflow + Gitee AI 搭建本地知识库问答机器人

本文详解 AutoFlow 从部署到配置的完整流程,包括数据库连接、模型设置、知识库创建及聊天引擎配置,实现了一行代码不用写的问答机器人快速搭建。轻松上手,助力开发者探索智能问答解决方案。

TiDB_PingCAP 的博客 1046

TiDB 分布式数据库多业务资源隔离应用实践

本文将分享某客户在 TiDB 分布式数据库中实现多业务资源隔离的实践案例。

TiDB_PingCAP 的博客 1317

攻克多版本运维难题:爱奇艺百套 TiDB 集群升级至 v7.1.5 实战宝典来袭!

本文将深入探讨爱奇艺如何通过升级,成功将百套 TiDB 集群从多个旧版本升级至 v7.1.5,攻克多版本运维挑战,获得更稳更快的 TiDB 使用体验。

TiDB_PingCAP 的博客 1157

百亿大表的实时分析:华安基金 HTAP 数据库的选型历程与 TiDB 使用体验

明确需求:首先评估业务对 TP(事务处理)和 AP(分析处理)的需求比重,确定数据量、查询速度和响应时间,确保数据库能满足业务对实时性的要求。技术特性评估:考虑数据库的实时分析能力、可扩展性、高性能、安全性和灵活性,以支持业务人员实施的场景需求,特别是后台营销人员对数据实时性的需求。集成与兼容性:评估数据库与现有数据库、应用程序和其他关键系统的集成能力,确保数据同步策略的无缝实施。安全性与可靠性:重视数据库的安全性措施、容灾备份机制、数据恢复能力和错误处理机制,保障业务连续性和数据安全。

TiDB_PingCAP 的博客 1019

TiDB 的高可用实践:一文了解代理组件 TiProxy 的原理与应用

TiDB 是一款典型的分布式存算分离架构的数据库,其中计算层由多个无状态的 TiDB Server 组成,这些 TiDB Server 同时对外承担连接请求。为了可以将连接分发到多个 TiDB Server 节点上,一般需要借助外部负载均衡组件如硬件负载均衡 F5、软件负载均衡 HAProxy 等。为了实现全链路的高可用架构,我们经常也需要考虑负载均衡组件本身的高可用性,比如通过 KeepAlived 来保证 HAProxy 的高可用。

TiDB_PingCAP 的博客 1255

你需要什么样的资源隔离?丨TiDB 资源隔离最佳实践

通过本文的学习,相信大家对 TiDB 的资源隔离能力有了更全面的理解;大家可以根据不同的场景需求,选择合适的资源隔离方案。如果您有新的资源隔离需求或场景,欢迎与我们联系。

TiDB_PingCAP 的博客 1254

狂飙 50 倍丨TiDB DDL 框架优化深度解析

前面我们介绍了 TiDB DDL 任务的整体执行流程。接下来,让我们聚焦到在线 Schema 变更的细节上。执行单步变更:Job Worker 会根据任务定义,执行一次在线 Schema 的变更。每一次变更都代表着 Schema 向目标状态迈进了一步,即进入下一个状态,可能的状态包括 write-only 和 delete-only 等。状态更新:完成单步变更后,Job Worker 会将当前的 Schema 状态更新到元数据中。

TiDB_PingCAP 的博客 1204

唐刘:TiDB 的 2024 - Cloud、SaaS 与 AI

最后再说下产品,在今年,我们发布了TiDB 8.1和8.5两个版本。在 2025 年,我们会有一个重大的改变,就是会持续的投入到 8.5 版本的质量加固,同时收敛新功能的开发,只会在 2025 年发布一个有更高质量的 LTS 版本。关于 TiDB 8 系列,我后面再写一篇文章详细的介绍一下吧。在 2024 年,我们交付了非常不错的成果,当然,能取得这样的成绩,来自于我们不断地交付优异的产品,满足客户的需求,赢得客户的信任。

TiDB_PingCAP 的博客 1054

PingCAP 连续两年入选 Gartner 云数据库管理系统魔力象限“荣誉提及”

TiDB 凭借领先的 HTAP 架构设计,支持用户在云上的数据库中同时运行关键业务交易和实时分析任务,充分享受云的弹性优势和业务连续性优势,助力企业实现数据敏捷。PingCAP 是业界领先的企业级开源分布式数据库企业,提供包括开源分布式数据库产品、解决方案与咨询、技术支持与培训认证服务,致力于为全球行业用户提供稳定高效、安全可靠、开放兼容的新型数据服务平台,解放企业生产力,加速企业数字化转型升级。

TiDB_PingCAP 的博客 706

TiDB 8.5 LTS 发版——支持无限扩展,开启 AI 就绪新时代

TiDB 8.5 扩展了Runaway Queries 的功能,新增“处理行数”和“用量(RU)”作为识别标准,实现更精确的识别,并允许将这些 Runaway Queries 放入一个资源可控的组中,确保在高负载环境下集群的稳定性。TiDB 8.5 通过实例级执行计划缓存功能,使得同一 TiDB 实例内的所有会话共享执行计划缓存,减少SQL编译时间,从而降低整体 SQL 运行时间,提高 OLTP 的性能和吞吐量,并有效地控制内存使用,提升数据库的稳定性。

TiDB_PingCAP 的博客 776

基于时间维度水平拆分的多 TiDB 集群统一数据路由/联邦查询技术的实践

通过该组件与 TiDB 分布式数据库的有效结合,可以实现近乎无容量上限的超大规模数据管理,尤其是对于重要程度高、吞吐量大、业务敏捷性强、数据冷热特征明显的业务系统。不仅能够支撑面向内外部客户业务无损的多维度、不受分片键制约的灵活高效访问,还可以有效控制和平衡单集群的负载、容量、资源利用率、稳定性等关键指标,在不增加过多复杂性的前提下实现更强的整体扩展能力。当然,组件的现有功能更多是聚焦在当前的客户场景,未来可以按需在功能性、易用性、高性能等方面进一步优化和提升。

TiDB_PingCAP 的博客 916

Rakuten 乐天积分系统从 Cassandra 到 TiDB 的选型与实战

Rakuten 乐天是一家成立于 1997 年的日本公司,总部位于东京,员工总数超过 30,000 人,业务遍及 100 多个国家和地区。除了电商业务外,乐天还涉及电信、金融等多个行业。乐天的积分系统在日本非常普及,用户通过使用乐天的服务,如银行卡、手机卡等,可以获得积分,并在乐天商城中使用这些积分进行购物或抵扣,我们每个季度还会举办促销活动、会有大量用户高频访问积分系统,因此,乐天积分服务平台的性能、延迟和可用性要求极高。

TiDB_PingCAP 的博客 1355

平凯星辰亮相开放原子开发者大会,TiDB 荣获年度活跃开源项目奖项

12 月 20 - 21 日,以“一切为了开发者”为主题的 2024 开放原子开发者大会暨首届开源技术学术大会在武汉成功举办。平凯星辰亮相本次大会,出品 AI 时代的数据库技术发展论坛,获评“校源行”优质开源课程合作单位。由平凯星辰创立的开源分布式数据库 TiDB 获评“2024 年度数据库领域国内活跃开源项目”,7 位 TiDB 开发者获评“2024 年度数据库领域国内活跃开源开发者”,彰显了 TiDB 在开源数据库领域的卓越影响力和社区活力。

TiDB_PingCAP 的博客 607

B 站数据库负责人赵月顺:助力海内外业务增长,百套 TiDB 的选型与运维实战

B 站的 TiDB 集群规模已达到 100 多套,计算节点超过 2000 个,存储节点超过 800 个。TiDB 的应用场景非常广泛,包括视频观看、一键三连、发送弹幕、撰写评论、阅读漫画以及视频后端的存储等。B 站的 TiDB 部署采取了存算分离的策略,计算节点被部署在容器中,这种做法的优势在于能够充分发挥容器化管理无状态服务达到水平弹性拓展能力,允许根据需求随时对计算节点进行扩展或缩减,整个过程仅需一次服务发版,有效提升了效率与灵活性。存储节点则继续部署在物理机上。

TiDB_PingCAP 的博客 1235

微众银行携手平凯星辰荣膺金融科技创新奖,共同打造纳管千台服务器的大规模数据库运维平台

在过去的十年中,平凯数据库在金融行业积累了丰富的实践经验,已经在国有大型银行的 PB 级别数据服务平台、头部商业银行的核心交易系统、头部保险公司的核心保单系统、头部证券公司的核心交易系统等领域,成功完成了对国外商业数据库和 MySQL 数据库的替换升级,部署了超过 1,000 套关键业务系统,集群节点总数超过了 10,000 个。为了应对这些挑战,同时满足金融行业对高可用、高可靠、高性能数据库的需求,微众银行开发了一套完整的运维体系,打造了大规模信创原生分布式数据库智能运维平台。

TiDB_PingCAP 的博客 805

知乎 PB 级别 TiDB 数据库集群管控实践

知乎的数据库团队以“致力于提供稳定、高效和易用的数据库服务”为目标,为公司业务团队提供更好的 TiDB 存储服务来应对高并发、复杂查询和大数据存储的需求。本文详细介绍了 TiDB 的生态架构,包括核心组件、数据迁移与同步、运维与监控平台、备份与恢复、生态集成、K8s 支持、工具集和安全与审计等方面。同时探讨了知乎如何在云上和云下环境中管控 TiDB 集群,以及如何通过自研的天穹平台实现数据库平台化建设,提升业务研发团队数据库变更和 DBA 团队的资源管控效率。

TiDB_PingCAP 的博客 1180

TiDB 优化器 | 执行计划管理及实践

本文深入解析了 TiDB 优化器的执行计划生成过程及其局限性,介绍了如何通过 Hint、SQL Binding、执行计划缓存等技术手段进行执行计划管理,确保查询性能的稳定性和高效性。

TiDB_PingCAP 的博客 1315

商业银行基于容器云的分布式数据库架构设计与创新实践

本文介绍了某商业银行基于 TiDB 和 Kubernetes(简称 K8s) 构建的云化分布式数据库平台,重点解决了传统私有部署模式下的高成本、低资源利用率及运维复杂等问题。通过引入 TiDB Operator 自动化管理与容器化技术,银行能够实现多个业务系统的高可用、弹性扩展与自动化运维,极大提高了运营效率与资源利用率。本文还详细阐述了平台架构设计、面临的技术挑战及创新解决方案,展示了 TiDB 在金融行业数字化转型中的应用前景。

TiDB_PingCAP 的博客 1360

PingCAP 荣膺 2024 亚马逊云科技合作伙伴两项殊荣

近日,在 2024 亚马逊云科技 re:Invent 全球大会上,PingCAP 荣膺亚马逊云科技年度技术合作伙伴和年度亚马逊云科技 Marketplace 合作伙伴两项殊荣。这是 PingCAP 连续第二年获得亚马逊云科技年度合作伙伴奖项,彰显了 PingCAP 在与亚马逊云科技合作服务客户的过程中所展现的卓越技术实力和专业服务能力,共同推动全球用户业务取得成功。

TiDB_PingCAP 的博客 569

基于 AutoFlow 快速搭建基于 TiDB 向量搜索的本地知识库问答机器人

通过本篇文章介绍,相信大家对使用 PingCAP 开源项目 AutoFlow 实现快速搭建基于 TiDB 的本地知识库问答机器人会有一个完整的了解。如果提前准备好 Docker、TiDB 环境,整个搭建过程估计在 10 分钟左右即可完成,无须开发任何代码。文中使用一篇 TiDB 文档作为本地数据源作为示例,在实际情况中,您可以基于自己的企业环境用同样的方法快速构造企业内部知识库问答机器人。

TiDB_PingCAP 的博客 1283

TiDB 关联子查询及半连接的优化实践

TiDB 针对子查询语句会执行多种子查询相关的优化,以提升子查询的执行性能。半连接语句和关联子查询语句是常用的两类子查询,TiDB 优化器默认包含一些自动优化策略,同时 TiDB 也提供额外的 HINT 用于影响优化器在特定场景下可以选择更高效的执行计划。本文针对半连接及关联子查询语句在 TiDB 中的用法及优化技巧进行说明。

TiDB_PingCAP 的博客 1405

实战丨证券 HTAP 混合业务场景的难点问题应对

某领先的全国性大型综合证券公司,坚持以核心业务为发展重心,并积极投身于前沿科技的应用创新。本文将分享该证券公司债权开放信息平台的构建经验,深入探讨如何利用 TiDB 分布式数据库成功应对 HTAP 场景下的挑战,满足数据实时性、可靠性、资源隔离、可维护性等要求。通过这一实践案例,我们可以看到 TiDB 如何在金融服务领域发挥关键作用,以及它如何帮助企业在激烈的市场竞争中保持领先地位。

TiDB_PingCAP 的博客 857
上一篇: TiDB × AI :DeepSeek 时代你需要什么样的数据基座
TiDB_PingCAP
TiDB_PingCAP 企业官方账号 企业官方账号
博客等级 码龄10年 2726粉丝 780原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值