You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Google Cloud Spanner无索引字段查询差异与扫描机制技术咨询

Spanner 无索引字段查询的差异问题解析

表结构定义

CREATE TABLE Account (
  ID STRING(100) NOT NULL,
  BSB STRING(20) NOT NULL,
  AccNum STRING(100) NOT NULL,
) PRIMARY KEY(ID);

背景信息

  • 表仅以ID作为主键,BSB和AccNum无索引、无唯一约束
  • 表存储1000万条记录,BSB重复率高,AccNum近似唯一
  • 查询表现:
    • 执行SELECT * FROM account WHERE AccNum = "001":查询计划显示"table scan on Account, rows returned:1",未触发全表扫描,耗时8ms
    • 执行SELECT * FROM account WHERE BSB = "100":查询计划显示"table scan on Account Full scan, row returned: 3,000,000",触发全表扫描,耗时30s

问题解答

1. 为何第二条SQL触发全表扫描,第一条却未触发?

核心原因是Spanner的查询优化器会根据过滤条件的预期返回行数选择执行策略:

  • 对于AccNum = "001",因为AccNum近似唯一,优化器预判返回行数极少(几乎1条),会采用分片并行扫描+提前终止的方式:Spanner的表按主键分片存储,它会同时扫描各个分片,一旦找到匹配记录就停止扫描剩余分片,所以不会触发全表扫描,耗时极短。
  • 对于BSB = "100",BSB重复率高,优化器预判会返回大量数据(300万条),此时分片扫描+提前终止的效率反而更低,不如直接全表扫描所有分片来获取全部匹配数据,因此触发全表扫描,耗时更长。

2. 若WHERE子句中的字段无索引,是否必然触发全表扫描?该认知是否正确?

这个认知不正确。
无索引不代表一定会全表扫描,Spanner的查询优化器会结合字段的统计信息(比如重复率、基数)、过滤条件的预期返回行数来选择最优执行策略:

  • 如果预判返回行数极少,会采用分片并行扫描+找到匹配后提前终止的方式,避免全表扫描;
  • 只有当预判返回行数较多时,才会选择全表扫描,因为此时提前终止的收益可以忽略,全表扫描的整体效率更高。

3. 第一条SQL未触发全表扫描,Spanner实际是如何查找对应记录的?

具体执行逻辑如下:

  1. 查询优化器基于AccNum的统计信息(近似唯一),判断该条件只会返回极少数记录,因此选择并行分片扫描策略。
  2. Spanner将Account表按主键ID分成多个分片,同时向所有分片发起扫描请求,每个分片在自己的范围内查找AccNum = "001"的记录。
  3. 一旦任意一个分片找到匹配的记录,Spanner会立即停止向剩余分片发送扫描请求,或通知已在扫描的分片终止扫描。
  4. 最后将找到的记录返回给客户端,整个过程因为提前终止,只扫描了部分分片而非全表,因此耗时很短。

内容的提问来源于stack exchange,提问作者pellucid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 02:07:22