摘要
TiDB 与 Elasticsearch 是两种定位截然不同的数据系统:TiDB 是面向事务和分析的关系型分布式数据库,Elasticsearch 是面向全文检索和实时搜索的分布式搜索引擎。在实际业务中,两者常常需要配合使用,各司其职。本文从核心能力、查询类型、数据一致性、性能特征四个维度进行系统对比,帮助技术团队理解两者的能力边界,并提供 TiDB + ES 混合方案的最佳实践。
本文适合谁:需要处理全文检索、复杂搜索查询的技术架构师,以及正在评估数据库与搜索引擎协作方案的技术负责人。
一、核心能力对比
1.1 定位与核心能力
| 维度 | TiDB | Elasticsearch |
|---|---|---|
| 系统定位 | 分布式关系型数据库(HTAP) | 分布式搜索引擎 |
| 核心能力 | 事务处理 + 实时分析 | 全文检索 + 实时搜索 |
| 数据模型 | 关系型(表 + 行 + 列) | 文档型(索引 + 文档/JSON) |
| 存储引擎 | TiKV(行存)+ TiFlash(列存) | Lucene(倒排索引) |
| 查询语言 | SQL | Query DSL / SQL(有限) |
| 事务支持 | 完整 ACID 分布式事务 | 单文档级别(无多文档事务) |
| 分析能力 | HTAP(行存 + 列存) | 聚合框架(Aggregations) |
| 文本处理 | 基础(全文索引、LIKE) | 专业(分词、同义词、评分、高亮) |
| SQL 兼容 | 完整 MySQL 兼容 | SQL 插件(功能有限) |
1.2 能力边界
TiDB 擅长:
├── 强一致性事务(ACID)
├── 复杂关系查询(JOIN、子查询、窗口函数)
├── 实时 OLTP + OLAP(HTAP)
├── 数据约束与完整性保证
└── MySQL 生态兼容
Elasticsearch 擅长:
├── 全文检索(分词、相关性评分、高亮)
├── 模糊搜索、同义词、拼写纠错
├── 多字段加权搜索
├── 地理位置搜索(Geo 查询)
├── 大规模日志与文本分析
└── 实时聚合统计(Aggregations)
二、查询类型对比
2.1 全文检索对比
-- TiDB:全文索引(ngram 分词,适合中文场景)
CREATE TABLE articles (
id BIGINT PRIMARY KEY AUTO_RANDOM,
title VARCHAR(200),
content TEXT,
FULLTEXT INDEX ft_title_content (title, content)
WITH PARSER ngram
);
-- 基础全文搜索
SELECT * FROM articles
WHERE MATCH(title, content) AGAINST('分布式数据库技术' IN NATURAL LANGUAGE MODE);
-- 带权重的匹配(无法实现字段级加权)
SELECT * FROM articles
WHERE MATCH(title, content) AGAINST('分布式数据库' IN BOOLEAN MODE);
// Elasticsearch:全文检索(专业分词 + 评分 + 高亮)
GET /articles/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"title": {
"query": "分布式数据库技术",
"boost": 3.0
}
}
},
{
"match": {
"content": {
"query": "分布式数据库技术",
"boost": 1.0
}
}
}
]
}
},
"highlight": {
"fields": {
"title": {},
"content": {}
}
},
"_source": ["id", "title", "published_at"]
}
2.2 查询能力详细对比
| 查询类型 | TiDB | Elasticsearch |
|---|---|---|
| 精确匹配 | 精确匹配(=、IN) | term 查询 |
| 范围查询 | 范围查询(BETWEEN、>、<) | range 查询 |
| 模糊匹配 | LIKE、全文索引 | match、fuzzy、wildcard |
| 全文分词检索 | FULLTEXT INDEX(ngram) | IK/jieba/standard 分词器 |
| 相关性评分 | 无(布尔匹配) | TF-IDF / BM25 评分 |
| 高亮显示 | 无内置支持 | 原生高亮(highlight) |
| 多字段加权搜索 | 无(FULLTEXT 不支持权重) | boost 参数灵活控制 |
| 同义词/拼音搜索 | 不支持 | Analysis 组件支持 |
| 拼写纠错 | 不支持 | Suggester 组件支持 |
| 自动补全 | 不支持 | Completion Suggester |
| 地理位置查询 | 空间函数(基础) | Geo 查询(丰富) |
| 多条件复合查询 | WHERE + AND/OR + NOT | bool 查询(must/should/filter/must_not) |
| 聚合统计 | GROUP BY + SUM/COUNT/AVG | Aggregations(terms、date_histogram、nested 等) |
| 分面搜索 | GROUP BY 实现 | Faceted Search(Aggregations) |
| 多表关联 | JOIN(优化器驱动) | 无原生 JOIN(需嵌套/父子文档) |
2.3 复杂业务查询对比
-- TiDB:多表 JOIN + 聚合(电商订单统计)
SELECT
c.province,
c.user_level,
COUNT(DISTINCT o.id) AS order_count,
SUM(o.amount) AS total_amount
FROM orders o
JOIN customers c ON o.customer_id = c.id
WHERE o.created_at BETWEEN '2026-01-01' AND '2026-06-30'
AND o.status = 'completed'
GROUP BY c.province, c.user_level
ORDER BY total_amount DESC
LIMIT 50;
-- 优势:多表 JOIN + 复杂聚合,执行效率高
// Elasticsearch:全文搜索 + 聚合(电商商品搜索 + 分面)
GET /products/_search
{
"query": {
"bool": {
"must": [
{ "match": { "title": "机械键盘" } }
],
"filter": [
{ "range": { "price": { "gte": 100, "lte": 2000 } } },
{ "term": { "status": "active" } }
]
}
},
"aggs": {
"categories": { "terms": { "field": "category.keyword" } },
"brand_count": { "cardinality": { "field": "brand.keyword" } },
"price_ranges": {
"range": {
"field": "price",
"ranges": [
{ "to": 300 },
{ "from": 300, "to": 800 },
{ "from": 800 }
]
}
}
},
"highlight": {
"fields": { "title": {} }
}
}
// 优势:全文搜索 + 相关性 + 分面聚合 + 高亮,一站式完成
三、数据一致性对比
| 一致性维度 | TiDB | Elasticsearch |
|---|---|---|
| 写入一致性 | 强一致(Raft 多数派) | 近实时(refresh 间隔,默认 1s) |
| 事务支持 | 完整 ACID 分布式事务 | 单文档原子操作,无多文档事务 |
| 数据副本 | Raft 协议多副本同步 | 主分片 + 副本分片(异步复制) |
| 数据延迟 | 毫秒级 | 秒级(refresh interval 控制) |
| 更新/删除 | 实时生效 | 软删除 + 段合并(延迟生效) |
| 数据版本控制 | MVCC(多版本并发控制) | _seq_no + _primary_term |
| 一致性校验 | 内置 checksum | _count API、_search API |
一致性差异的影响
写入路径对比:
TiDB 写入路径:
应用 → TiDB Server → Raft 多数派写入 → 立即可查询(强一致)
延迟:毫秒级
Elasticsearch 写入路径:
应用 → ES Node → 索引缓冲区 → refresh(默认1s)→ 可搜索
延迟:秒级(refresh 间隔内不可搜索)
关键差异:
- TiDB 写入后立即可查询(强一致性)
- ES 写入后需要等待 refresh 才能被搜索(近实时)
- ES 不支持跨文档事务,无法保证关联文档的原子性
四、性能特征对比
4.1 吞吐与延迟对比
| 性能指标 | TiDB | Elasticsearch |
|---|---|---|
| 写入吞吐 | 5-10 万 TPS(行级写入) | 5-50 万 docs/s(批量写入) |
| 写入延迟 | < 5ms | < 1ms(索引写入,searchable 延迟 1s) |
| 点查延迟 | < 1ms(主键查询) | < 5ms(ID 查询) |
| 全文搜索延迟 | 10-100ms(ngram 索引) | 5-50ms(倒排索引 + BM25) |
| 聚合查询延迟 | 100ms-数秒(取决于复杂度) | 50ms-数秒(Aggregations) |
| JOIN 查询 | 优秀(优化器驱动) | 不支持(需嵌套文档或应用层) |
| 并发连接数 | 千级 | 千级 |
4.2 存储效率对比
| 存储指标 | TiDB | Elasticsearch |
|---|---|---|
| 存储模型 | 行存 + 列存(TiFlash) | 倒排索引 + 列存(doc_values) |
| 压缩比 | 行存 1:1 ~ 3:1,列存更高 | 倒排索引 2:1 ~ 5:1 |
| 索引开销 | 适中(B+ Tree) | 较高(倒排索引 + doc_values + keyword) |
| 磁盘使用 | 中等(数据量 × 副本数) | 较高(索引开销 × 副本数) |
五、混合方案:TiDB + Elasticsearch
5.1 架构设计
在实际业务中,TiDB 作为主数据存储,Elasticsearch 作为搜索索引层,是最常见的组合方案:
TiDB + Elasticsearch 混合架构:
┌──────────┐ ┌──────────────────────────────────────────┐
│ 应用层 │────▶│ 数据写入路径 │
└──────────┘ │ 业务写入 → TiDB(主存储,强一致) │
│ │ │
│ ▼ │
│ TiCDC / Canal │
│ │ │
│ ▼ │
│ Kafka │
│ │ │
│ ▼ │
│ Logstash / 自定义消费者 │
│ │ │
│ ▼ │
│ Elasticsearch(搜索索引) │
└──────────────────────────────────────────┘
┌──────────┐ ┌──────────────────────────────────────────┐
│ 应用层 │────▶│ 查询路径 │
└──────────┘ │ │
│ 全文搜索 / 模糊搜索 → Elasticsearch │
│ 精确查询 / 事务操作 → TiDB │
│ 复杂报表 / OLAP → TiDB TiFlash │
└──────────────────────────────────────────┘
5.2 数据同步方案
| 同步方案 | 延迟 | 可靠性 | 复杂度 |
|---|---|---|---|
| TiCDC → Kafka → Logstash → ES | 秒级 | 高(CDC 保证不丢) | 中 |
| Canal → Kafka → ES | 秒级 | 高 | 中 |
| 应用双写(TiDB + ES) | 毫秒级 | 中(需补偿机制) | 低 |
| TiDB 全文索引(无 ES) | 毫秒级 | 高 | 最低 |
5.3 查询路由策略
# 伪代码:查询路由策略
def route_query(request):
if request.query_type == 'fulltext_search':
# 全文检索、模糊搜索、相关性排序 → ES
return elasticsearch.search(request.dsl)
elif request.query_type == 'exact_match':
# 精确查询、主键查询 → TiDB
return tidb.execute(request.sql)
elif request.query_type == 'transaction':
# 事务操作(写入、更新) → TiDB
return tidb.execute(request.sql)
elif request.query_type == 'analytics':
# 复杂报表、OLAP → TiDB TiFlash
return tidb.execute(request.sql, engine='tiflash')
elif request.query_type == 'composite':
# 组合查询:先从 ES 搜索获取 ID 列表,再从 TiDB 获取完整数据
ids = elasticsearch.search_id_list(request.dsl)
return tidb.execute(f"SELECT * FROM table WHERE id IN ({ids})")
5.4 适用场景分工
| 场景 | 推荐 | 原因 |
|---|---|---|
| 商品全文搜索 | ES | 分词 + 评分 + 高亮 + 分面 |
| 用户登录/鉴权 | TiDB | 强一致事务 + 精确查询 |
| 订单管理 | TiDB | 事务一致性 + 复杂 JOIN |
| 文章/帖子搜索 | ES | 全文检索 + 相关性排序 |
| 数据报表 | TiDB TiFlash | HTAP + 复杂聚合 |
| 日志分析 | ES | 全文搜索 + 聚合分析 |
| 财务结算 | TiDB | 强一致 + 审计 + 事务 |
FAQ
Q1:TiDB 的 FULLTEXT INDEX 能否替代 Elasticsearch 的全文检索?
TiDB 的 FULLTEXT INDEX 适合基础的全文搜索需求(如后台管理系统的内容搜索),但与 Elasticsearch 存在显著差距:TiDB 不支持相关性评分(BM25)、搜索结果高亮、同义词扩展、拼音搜索、自动补全、多字段加权等高级搜索功能。对于面向用户的搜索场景,建议使用 Elasticsearch。
Q2:TiDB + Elasticsearch 数据同步延迟如何控制?
使用 TiCDC → Kafka → Logstash 的方案,端到端延迟通常在 1-3 秒。如果需要更低延迟,可以优化 Kafka 消费者的批量参数,或使用应用层双写方案(但需要实现补偿机制处理失败场景)。TiCDC 保证了不丢数据,但延迟受 Kafka 和 Logstash 的处理能力影响。
Q3:Elasticsearch 能否作为主数据存储?
技术上可以,但不推荐。Elasticsearch 缺少完整的事务支持、复杂关系查询能力(JOIN)、严格的数据约束(如外键、唯一约束),在数据一致性和完整性方面不如关系型数据库。ES 更适合作为搜索索引层,主数据仍然存储在 TiDB 等数据库中。
Q4:如果不需要高级搜索功能,只用 TiDB 的全文索引是否更简单?
是的。如果搜索需求仅限于基础的全文匹配(如后台管理系统的关键词搜索),TiDB 的 FULLTEXT INDEX 完全足够。这样可以避免引入 Elasticsearch 的额外架构复杂度(ES 集群运维、数据同步管道、双写/同步机制)。评估的关键标准是:是否需要相关性排序、搜索高亮、同义词/拼音、自动补全等高级功能。
总结
TiDB 和 Elasticsearch 在数据技术栈中扮演着完全不同的角色。TiDB 是核心数据的"真相之源",负责强一致的事务处理和复杂关系查询;Elasticsearch 是搜索能力的"加速器",负责全文检索、相关性排序和实时搜索体验。
在实际业务中,两者不是替代关系,而是互补关系。TiDB + Elasticsearch 的混合架构是搜索密集型应用的最佳实践:TiDB 保证数据的完整性和一致性,ES 提供专业的搜索体验。对于搜索需求简单的场景,TiDB 内置的 FULLTEXT INDEX 可以独立满足需求,避免额外架构复杂度。
下一步行动
- 试用 TiDB:体验 TiDB 的关系型分布式能力,验证全文索引和 HTAP 分析性能。
- 获取搜索场景解决方案:了解 TiDB + Elasticsearch 混合架构在电商、内容平台等搜索场景的最佳实践。
- 申请 POC 测试:基于您的搜索场景和数据量,获取 TiDB + ES 混合方案的专属评估。