使用 TiDB 读取 TiFlash 副本
本文介绍了如何使用 TiDB 读取 TiFlash 副本。
TiDB 提供了三种方式来读取 TiFlash 副本。如果你添加了 TiFlash 副本且没有进行引擎配置,默认使用的是 CBO(基于成本的优化)模式。
智能选择
对于具有 TiFlash 副本的表,TiDB 优化器会根据成本估算自动判断是否使用 TiFlash 副本。你可以使用 desc
或 explain analyze
语句来检查是否选择了 TiFlash 副本。例如:
desc select count(*) from test.t;
+--------------------------+---------+--------------+---------------+--------------------------------+
| id | estRows | task | access object | operator info |
+--------------------------+---------+--------------+---------------+--------------------------------+
| StreamAgg_9 | 1.00 | root | | funcs:count(1)->Column#4 |
| └─TableReader_17 | 1.00 | root | | data:TableFullScan_16 |
| └─TableFullScan_16 | 1.00 | cop[tiflash] | table:t | keep order:false, stats:pseudo |
+--------------------------+---------+--------------+---------------+--------------------------------+
3 rows in set (0.00 sec)
explain analyze select count(*) from test.t;
+--------------------------+---------+---------+--------------+---------------+----------------------------------------------------------------------+--------------------------------+-----------+------+
| id | estRows | actRows | task | access object | execution info | operator info | memory | disk |
+--------------------------+---------+---------+--------------+---------------+----------------------------------------------------------------------+--------------------------------+-----------+------+
| StreamAgg_9 | 1.00 | 1 | root | | time:83.8372ms, loops:2 | funcs:count(1)->Column#4 | 372 Bytes | N/A |
| └─TableReader_17 | 1.00 | 1 | root | | time:83.7776ms, loops:2, rpc num: 1, rpc time:83.5701ms, proc keys:0 | data:TableFullScan_16 | 152 Bytes | N/A |
| └─TableFullScan_16 | 1.00 | 1 | cop[tiflash] | table:t | tiflash_task:{time:43ms, loops:1, threads:1}, tiflash_scan:{...} | keep order:false, stats:pseudo | N/A | N/A |
+--------------------------+---------+---------+--------------+---------------+----------------------------------------------------------------------+--------------------------------+-----------+------+
cop[tiflash]
表示该任务会被发送到 TiFlash 进行处理。如果你没有选择 TiFlash 副本,可以尝试使用 analyze table
语句更新统计信息,然后再用 explain analyze
查看结果。
注意,如果一个表只有单个 TiFlash 副本且相关节点无法提供服务,在 CBO 模式下的查询会反复重试。在这种情况下,你需要指定引擎或使用手动提示从 TiKV 副本读取数据。
引擎隔离
引擎隔离是通过配置相应变量,指定所有查询都使用指定引擎的副本。可选的引擎有 "tikv"、"tidb"(表示 TiDB 的内部内存表区域,存储一些 TiDB 系统表,用户不能主动使用)和 "tiflash"。
你可以使用以下语句指定引擎:
set @@session.tidb_isolation_read_engines = "engine list separated by commas";
或者
set SESSION tidb_isolation_read_engines = "engine list separated by commas";
如果查询的表没有指定引擎的副本(例如,配置为 "tiflash" 但该表没有 TiFlash 副本),查询会返回错误。
手动提示
手动提示可以在满足引擎隔离的前提下,强制 TiDB 对特定表或语句使用指定的副本。以下是使用手动提示的示例:
select /*+ read_from_storage(tiflash[table_name]) */ ... from table_name;
如果在查询语句中为表设置了别名,必须在包含提示的语句中使用别名,提示才会生效。例如:
select /*+ read_from_storage(tiflash[alias_a,alias_b]) */ ... from table_name_1 as alias_a, table_name_2 as alias_b where alias_a.column_1 = alias_b.column_2;
上述语句中,tiflash[]
提示优化器读取 TiFlash 副本。你也可以使用 tikv[]
提示优化器读取 TiKV 副本。关于提示语法的详细信息,请参考 READ_FROM_STORAGE。
如果提示指定的表没有对应引擎的副本,提示会被忽略并报告警告。此外,提示仅在引擎隔离的前提下生效。如果提示中指定的引擎不在引擎隔离列表中,也会被忽略并报告警告。
智能选择、引擎隔离和手动提示的关系
在上述三种读取 TiFlash 副本的方式中,引擎隔离定义了引擎副本的整体范围;在此范围内,手动提示提供了更细粒度的语句级和表级引擎选择;最终,优化器会在指定的引擎列表中,根据成本估算自动选择更优的引擎副本。