开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第5天,点击查看活动详情
在前一篇文章juejin.cn/post/717218… 我们提到使用SELECT * from examples.concurrent_executions去查找10w条全部超时的记录,100%卡住,这里面为何yugabyteDB没用使用file filter过滤掉不必要的数据呢?今天啃了一天代码,记录如下:
其实真实答案是,yugabyteDB根本没有实现!select * from table 时,底层是转化为Scan的,最开始的入口为:
Status QLReadOperation::Execute(const YQLStorageIf& ql_storage,
CoarseTimePoint deadline,
const ReadHybridTime& read_time,
const DocReadContext& doc_read_context,
const Schema& projection,
QLResultSet* resultset,
HybridTime* restart_read_ht) {
const auto& schema = doc_read_context.schema;
//根據SQL 條件構建Spec
ql_storage.BuildYQLScanSpec(
request_, read_time, schema, read_static_columns, static_projection, &spec,
&static_row_spec);
//spec可以根據where條件謂詞,生成seek iter ,注意這裏有我們想要的filter
ql_storage.GetIterator(
request_, projection, doc_read_context, txn_op_context_, deadline, read_time,
*spec, &iter));
....
}
这里有重要的spec构建迭代器,输出iter。Spec对象是用SQL的的where条件,if条件构建的。
//注意这里是QLScan强制转换为DocQLScanSpec
DoInit(down_cast<const DocQLScanSpec&>(spec));
//注意QLScanSpec有很多参数,都是根据sql的条件变量构建的
QLScanSpec(const QLConditionPB* condition,
const QLConditionPB* if_condition,
const bool is_forward_scan,
QLExprExecutorPtr executor = nullptr);
看到ql_storage是一个基类YQLStorageIf,真實對象是:src/yb/docdb/ql_rocksdb_storage.cc的一個實現
class QLRocksDBStorage : public *YQLStorageIf*。我们发现成员变量的迭代器,是DocRowwiseIterator:
Status QLRocksDBStorage::GetIterator(...)
auto doc_iter = std::make_unique<DocRowwiseIterator>(
projection, doc_read_context, txn_op_context, doc_db_, deadline, read_time);
//接下来根据spec初始化迭代器,我们来看看怎么实现的
doc_iter->Init(spec);
Status DocRowwiseIterator::Init(const QLScanSpec& spec) {
table_type_ = TableType::YQL_TABLE_TYPE;
return DoInit(down_cast<const DocQLScanSpec&>(spec));
}
我们看到了自己最想要的迭代器构建:确实doc_spec.CreateFileFilter()有创建file filter,但是我们的SQL却没用任何condition 部分,所以无法构建CreateFileFilter。至此,我们select 超时的原因已经找到:
Status DocRowwiseIterator::DoInit(const T& doc_spec) {
db_iter_ = CreateIntentAwareIterator(
doc_db_, mode, lower_doc_key.AsSlice(), doc_spec.QueryId(), txn_op_context_,
deadline_, read_time_, doc_spec.CreateFileFilter());
也就是说,SELECT * from examples.concurrent_executions 这种sql,没有任何SQL where condition,也不支持TTL 做condition,是不能去过滤TTL sst的,也比较好理解,因为yugabyteDB不是一个时序数据库,TTL可能散乱在任何SST文件中,在散乱的TTL key、row聚合成的sst,或者经过compaction将这些不同的TTL的key聚合到一个SST文件,CreateFileFilter将无法发挥作用(他们也没有去优化、实现)。