0

查询计划显示了一个集合扫描,它遍历了 mongo 集合中的所有行。因此,我在 where 子句列上创建了一个索引,期望 Drill 选择基于索引的访问计划。但是钻继续使用全表扫描。为了让钻头使用索引,还有其他事情要做吗?

下面给出了实际查询、生成的查询计划和 mongo 索引。

SQL:

    Select j.user as User, TO_DATE(j.created_at) as submitted_on
    from mongo.example.jobs j
    where j.user = 'john@example.ai' and j.created_at BETWEEN timestamp '2020-03-25 13:12:55' AND timestamp '2020-04-24 13:12:55'

物理计划(来自钻取 UI)

    00-00 Screen : rowType = RecordType(ANY User, ANY submitted_on): rowcount = 121.2375, cumulative cost = {6720.59875 rows, 23532.19875 cpu, 895541.0 io, 0.0 network, 0.0 memory}, id = 10468
    00-01 Project(User=[$0], submitted_on=[TO_DATE($1)]) : rowType = RecordType(ANY User, ANY submitted_on): rowcount = 121.2375, cumulative cost = {6708.475 rows, 23520.075 cpu, 895541.0 io, 0.0 network, 0.0 memory}, id = 10467
    00-02 SelectionVectorRemover : rowType = RecordType(ANY user, ANY created_at): rowcount = 121.2375, cumulative cost = {6587.2375 rows, 22913.8875 cpu, 895541.0 io, 0.0 network, 0.0 memory}, id = 10466
    00-03 Filter(condition=[AND(=($0, 'john@example.ai'), >=($1, 2020-03-25 13:12:55), <=($1, 2020-04-24 13:12:55))]) : rowType = RecordType(ANY user, ANY created_at): rowcount = 121.2375, cumulative cost = {6466.0 rows, 22792.65 cpu, 895541.0 io, 0.0 network, 0.0 memory}, id = 10465
    00-04 Scan(table=[[mongo, example, jobs]], groupscan=[MongoGroupScan [MongoScanSpec=MongoScanSpec [dbName=example, collectionName=jobs, filters=null], columns=[`user`, `created_at`]]]) : rowType = RecordType(ANY user, ANY created_at): rowcount = 3233.0, cumulative cost = {3233.0 rows, 6466.0 cpu, 895541.0 io, 0.0 network, 0.0 memory}, id = 10464

在 MongoDB 中创建的索引

{
"v" : 2,
"key" : { "user" : 1, "created_at" : 1, "method_map_id" : 1 },
"name" : "user_1_created_at_1_method_map_id_1",
"ns" : "example.jobs"
}

此外,在钻头文档中,我看到钻头仅支持 MapR DB 的索引。这是否意味着不会使用其他数据源(如 mongo)的索引?

https://drill.apache.org/docs/querying-indexes-introduction/

4

1 回答 1

0

问题在于处理时间戳过滤谓词的 mongo-storage 插件。过滤谓词按给定顺序在以下模块中进行评估。

MongoPushDownFilterForScan -> MongoFilterBuilder -> MongoCompareFunctionProcessor.process() -> MongoCompareFunctionProcessor.visitSchemaPath()

visitSchemaPath 方法的作用类似于值表达式类的 getter 方法。我看到 TimestampExpression 没有处理程序。添加了下面的代码,重新构建并测试了它。

if (valueArg instanceof TimeStampExpression) {
 Long unixseconds = ((TimeStampExpression) valueArg).getTimeStamp();
 this.value = new Date(unixseconds);
 this.path = path;
 return true;
 }

这使得时间戳过滤器被传递到 mongo 查询的过滤器部分。

于 2020-05-29T09:41:43.470 回答