10分钟上手:用Quickwit为ClickHouse打造极速全文搜索引擎
10分钟上手:用Quickwit为ClickHouse打造极速全文搜索引擎
你是否遇到过ClickHouse模糊查询卡顿、日志检索耗时过长的问题?作为列式数据库的佼佼者,ClickHouse在结构化数据分析中表现卓越,但面对非结构化文本搜索时却力不从心。本文将带你通过Quickwit的Elasticsearch兼容API,为ClickHouse添加毫秒级全文搜索能力,无需重构现有数据架构。
方案架构:ClickHouse与Quickwit的协同设计
Quickwit作为云原生搜索引擎,通过S3/对象存储实现低成本存储,同时提供亚秒级查询响应。其与ClickHouse的集成采用"双写+互补查询"模式:核心业务数据写入ClickHouse保障分析性能,全文检索字段同步写入Quickwit,查询时通过联合接口获取结果。
技术优势对比
| 特性 | ClickHouse | Quickwit |
|---|---|---|
| 全文检索 | 依赖like/ilike(O(n)复杂度) | 倒排索引+BM25算法(O(1)复杂度) |
| 模糊匹配 | 不支持通配符前缀查询 | 原生支持前缀/短语/正则匹配 |
| 存储成本 | 本地存储,扩展成本高 | 对象存储,按需付费 |
| 查询延迟 | 秒级(大量文本扫描) | 亚秒级(索引优化) |
实现步骤:从部署到查询的全流程
1. 部署Quickwit服务
# 克隆仓库
git clone https://gitcode.com/GitHub_Trending/qu/quickwit
cd quickwit
# 启动服务(默认使用本地存储)
./quickwit run
服务启动后可通过http://localhost:7280访问管理界面,更多部署选项参见官方部署文档。
2. 创建索引模式
通过Elasticsearch兼容API创建适配ClickHouse数据结构的索引:
# 创建索引配置文件(适配ClickHouse日志表结构)
cat > clickhouse-logs.yaml << EOF
version: 0.7
index_id: clickhouse-logs
doc_mapping:
field_mappings:
- name: log_time
type: datetime
input_formats: [rfc3339, unix_timestamp]
output_format: unix_timestamp
- name: query
type: text
tokenizer: default
- name: user
type: keyword
- name: database
type: keyword
EOF
# 应用索引配置
./quickwit index create --config clickhouse-logs.yaml
索引配置细节可参考索引配置文档,其中text类型字段会自动构建倒排索引。
3. 数据同步方案
方案A:通过Kafka中间件(推荐)
-- ClickHouse创建物化视图,将数据写入Kafka
CREATE MATERIALIZED VIEW logs_to_kafka
ENGINE = Kafka('kafka:9092', 'clickhouse-logs', 'consumer-group', 'JSONEachRow')
AS SELECT log_time, query, user, database FROM system.query_log;
Quickwit通过Kafka源连接:
# 在quickwit.yaml中添加数据源
sources:
- source_id: clickhouse-kafka
type: kafka
params:
topic: clickhouse-logs
bootstrap_servers: "kafka:9092"
group_id: "quickwit-consumer"
index_id: clickhouse-logs
方案B:通过HTTP批量写入
# Python示例:从ClickHouse查询并批量写入Quickwit
import requests
from clickhouse_driver import Client
client = Client('clickhouse-host')
rows = client.execute('SELECT log_time, query, user, database FROM system.query_log LIMIT 10000')
# 构造Elasticsearch Bulk格式数据
bulk_data = []
for row in rows:
bulk_data.append('{"create": {}}')
bulk_data.append(json.dumps({
"log_time": row[0].timestamp(),
"query": row[1],
"user": row[2],
"database": row[3]
}))
# 发送到Quickwit Bulk API
response = requests.post(
'http://quickwit:7280/api/v1/_elastic/_bulk',
data='\n'.join(bulk_data),
headers={'Content-Type': 'application/json'}
)
批量写入API详细规范见ES兼容API文档。
4. 执行联合查询
通过Quickwit的ES兼容API执行全文检索,再关联ClickHouse数据:
# 1. Quickwit检索相关日志
search_response = requests.post(
'http://quickwit:7280/api/v1/_elastic/clickhouse-logs/_search',
json={
"query": {
"match_phrase": {
"query": "ALTER TABLE" # 查找包含ALTER TABLE的SQL语句
}
},
"size": 100
}
)
hits = search_response.json()['hits']['hits']
log_times = [hit['_source']['log_time'] for hit in hits]
# 2. ClickHouse查询关联指标
client.execute('''
SELECT user, count(*) as query_count
FROM system.query_log
WHERE log_time IN %(log_times)s
GROUP BY user
''', {'log_times': log_times})
优化与监控
性能调优
- 索引优化:对高频查询字段设置
fast属性
- name: user
type: keyword
fast: true # 加速聚合查询
- 分片策略:按时间分区索引
# 在索引配置中添加
partitioning:
by_field: log_time
partition_duration: 1d # 按天分区
- 缓存配置:调整搜索结果缓存
# quickwit.yaml中设置
searcher:
split_cache_capacity: 10GB # 提高热点数据缓存
监控集成
Quickwit暴露Prometheus指标,可通过Grafana监控:
# prometheus.yml配置
scrape_configs:
- job_name: 'quickwit'
static_configs:
- targets: ['quickwit:7280']
监控面板配置参见监控文档,典型监控指标包括quickwit_search_latency_seconds和quickwit_indexing_docs_total。
实际案例:优化慢查询日志分析
某电商平台将ClickHouse慢查询日志接入Quickwit后,实现以下场景优化:
- 异常SQL审计:通过
match_phrase: {query: "DELETE FROM orders"}快速定位危险操作 - 用户行为分析:结合
aggs: {terms: {field: "user", size: 10}}统计高频查询用户 - 性能瓶颈定位:通过
range: {log_time: {gte: "now-1h"}}+sort: {duration: "desc"}找出最近一小时慢查询
总结与扩展
通过本文方法,你已成功为ClickHouse添加企业级全文搜索能力。后续可探索:
- 权限控制:集成LDAP实现细粒度访问控制
- 多集群部署:参考Kubernetes部署实现高可用
- 高级查询:使用聚合功能进行日志趋势分析
完整代码示例可在教程目录找到,如有问题可查阅FAQ文档或提交issue。
提示:生产环境建议使用对象存储(S3/MinIO)作为存储后端,并配置适当的备份策略。
更多推荐



所有评论(0)