阿里云 OTS 四种读取方式 + 索引关系
六爷批评得对!我刚才没结合索引讲,不够透彻!🥚
重新来,结合索引给你讲清楚!
📊 四种读取方式 + 索引关系
| API | 走什么索引 | 扫描方式 | 性能 | 适用场景 |
|---|---|---|---|---|
| GetRange | 主键索引(聚簇索引) | 范围扫描 | ⭐⭐⭐⭐ | 主键连续范围 |
| BatchGetRow | 主键索引(聚簇索引) | 点查 | ⭐⭐⭐⭐⭐ | 已知主键批量读 |
| RangeIterator | 主键索引(聚簇索引) | 全表扫描 | ⭐⭐ | 导出/全量扫描 |
| Filter | ❌ 不走索引 | 全表扫描后过滤 | ⭐ | 额外条件 |
| SearchIndex | 多元索引(二级索引) | 索引扫描 | ⭐⭐⭐⭐⭐ | 非主键查询 |
🗺️ 索引结构对比
主键索引(聚簇索引)
ChargerecordLogs 表
主键:[Txsn, EndTime]
物理存储顺序(按主键排序):
┌─────────────┬──────────────┬────────────┐
│ Txsn │ EndTime │ 数据 │
├─────────────┼──────────────┼────────────┤
│ txsn_001 │ 1756800000 │ {...} │
│ txsn_002 │ 1756800100 │ {...} │
│ txsn_003 │ 1756800200 │ {...} │
│ txsn_004 │ 1756800300 │ {...} │
│ txsn_005 │ 1756800400 │ {...} │
└─────────────┴──────────────┴────────────┘
↑
└── 按 Txsn 排序,EndTime 二级排序
GetRange 走这个索引!
多元索引(二级索引)
ChargerecordLogs_index 多元索引
索引字段:[EndTime, Txsn, Deviceno, ...]
索引结构(倒排索引):
┌──────────────┬──────────────────────────┐
│ EndTime │ 行 ID 列表 │
├──────────────┼──────────────────────────┤
│ 1756800000 │ [row_001, row_050, ...] │
│ 1756800100 │ [row_002, row_033, ...] │
│ 1756800200 │ [row_003, row_077, ...] │
└──────────────┴──────────────────────────┘
↑
└── 可以按 EndTime 快速定位
SearchIndex 走这个索引!
1️⃣ GetRange + 主键索引
走主键索引,范围扫描
csharp
// 主键:[Txsn, EndTime]
var startPk = new PrimaryKeyBuilder()
.AddColumn("txsn", new ColumnValue("txsn_001"))
.AddColumn("endtime", new ColumnValue(1756800000))
.Build();
var endPk = new PrimaryKeyBuilder()
.AddColumn("txsn", new ColumnValue("txsn_999"))
.AddColumn("endtime", new ColumnValue(1757000000))
.Build();
var request = new GetRangeRequest
{
TableName = "ChargerecordLogs",
InclusiveStartPrimaryKey = startPk,
ExclusiveEndPrimaryKey = endPk
};
索引扫描过程:
1. 定位到 txsn_001(主键索引 B+ 树)
2. 顺序扫描到 txsn_999
3. 返回范围内的所有行
✅ 走主键索引
✅ 物理存储连续,扫描快
❌ 只能按主键范围查(不能单查 EndTime)
适用场景:
- ✅ 已知 Txsn 范围,查这段时间的所有记录
- ❌ 只查 EndTime 范围(Txsn 未知)→ 走不了索引!
2️⃣ BatchGetRow + 主键索引
走主键索引,点查
csharp
var request = new BatchGetRowRequest
{
TableName = "ChargerecordLogs",
Rows = new List<PrimaryKey>
{
new PrimaryKeyBuilder().AddColumn("txsn", new ColumnValue("txsn_001")).Build(),
new PrimaryKeyBuilder().AddColumn("txsn", new ColumnValue("txsn_050")).Build(),
new PrimaryKeyBuilder().AddColumn("txsn", new ColumnValue("txsn_100")).Build()
}
};
索引扫描过程:
1. txsn_001 → B+ 树定位 → 读取
2. txsn_050 → B+ 树定位 → 读取
3. txsn_100 → B+ 树定位 → 读取
✅ 走主键索引
✅ 点查,O(logN) 复杂度
❌ 必须知道完整主键
适用场景:
- ✅ 已知 Txsn 列表,查详情
- ❌ Txsn 未知 → 用不了
3️⃣ RangeIterator + 主键索引
走主键索引,全表扫描
csharp
var iterator = client.CreateRangeIterator(
"ChargerecordLogs",
GetRangeDirection.Forward,
startPk, // txsn_001
endPk, // txsn_999999
1000
);
索引扫描过程:
1. 从 txsn_001 开始
2. 顺序扫描主键索引
3. 自动分页,直到 txsn_999999
✅ 走主键索引
✅ 自动分页,不用自己处理
❌ 全表扫描,慢
适用场景:
- ✅ 导出全量数据
- ✅ 后台离线任务
- ❌ 实时查询 → 太慢
4️⃣ Filter + ❌ 不走索引
全表扫描后过滤
csharp
var request = new GetRangeRequest
{
TableName = "ChargerecordLogs",
InclusiveStartPrimaryKey = startPk,
ExclusiveEndPrimaryKey = endPk,
Filter = new RelationalCondition(
"endtime",
CompareOperator.GREATER_THAN,
new ColumnValue(1756800000)
)
};
扫描过程:
1. 扫描主键索引(按 Txsn 顺序)
2. 读取每一行数据
3. 用 Filter 判断 EndTime 是否符合
4. 返回符合条件的行
❌ 不走 EndTime 索引
❌ 全表扫描(即使只有 1 行符合,也要扫全部)
❌ CU 消耗巨大
为什么慢:
假设 100 万行,只有 100 行 EndTime 符合:
- 扫描:100 万行
- 过滤:100 万行
- 返回:100 行
CU 消耗 = 100 万行 ❌
5️⃣ SearchIndex + 多元索引
走多元索引,索引扫描
csharp
var request = new SearchRequest
{
TableName = "ChargerecordLogs",
IndexName = "ChargerecordLogs_index",
SearchQuery = new SearchQuery
{
Query = new RangeQuery("endtime")
{
GreaterThanEquals = 1756800000,
LessThan = 1757000000
}
}
};
索引扫描过程:
1. 在多元索引中定位 EndTime 范围
2. 直接拿到符合条件的行 ID 列表
3. 返回数据(或聚合结果)
✅ 走 EndTime 多元索引
✅ 只扫描符合条件的行
✅ CU 消耗 = 符合条件的行数
为什么快:
假设 100 万行,100 行 EndTime 符合:
- 扫描:100 行(多元索引直接定位)
- 返回:100 行
CU 消耗 = 100 行 ✅
🎯 你的场景(充电记录按 EndTime 查询)
| 方案 | 走什么索引 | 扫描行数 | CU 消耗 | 结果 |
|---|---|---|---|---|
| SQL + WHERE EndTime | ❌ 无 | 100 万 | 10 万配额超限 | ❌ 报错 |
| GetRange + Filter | 主键索引 | 100 万 | 100 万 | ❌ 太慢 |
| SearchIndex | 多元索引 | 100 行 | 100 行 | ✅ 秒杀 |
💡 一句话总结
| API | 索引 | 本质 |
|---|---|---|
| GetRange | 主键索引 | 按主键范围扫 |
| BatchGetRow | 主键索引 | 按主键点查 |
| RangeIterator | 主键索引 | 按主键全表扫 |
| Filter | ❌ 无索引 | 全表扫后过滤 |
| SearchIndex | 多元索引 | 按索引字段扫 |
六爷,你这个 EndTime 查询,必须用 SearchIndex + 多元索引,其他都慢!🔥

浙公网安备 33010602011771号