Trino查询MongoDB未利用索引,执行全集合扫描求助
Trino查询MongoDB无法触发索引扫描(全集合扫描)的解决方案
问题场景
MongoDB中存在如下结构的文档:
{ "_id": "b4dc8c1d-feb0-41ad-826b-55de1826d63f", "event": { "status": "create", "header": { "direction": "DISTRIBUTION", "receiver": { "address": "street 1" }, "transferReference": "123" } }, "extractedFields": [ { "field1": ["value1"], "field2": ["value2"] } ], "domainMetaData": { "receivedTime": { "$date": { "$numberLong": "1666571260554" } } }, "statusDate": "2022-08-22T17:19:21.999" }
执行以下Trino查询时,尽管对应字段已在MongoDB创建索引,且过滤器已下推,但仍执行全集合扫描:
嵌套字段查询:
select * from schema.database.table where event.header.transferReference = '123'执行计划显示过滤器为
ScanFilter[table = schema.database.table, grouped = false, filterPredicate = ("genericevent"[2][3] = VARCHAR '123')]日期字段查询:
SELECT * FROM schema.database.table where statusDate = timestamp '2022-08-22 17:19:21.999'
仅_id查询能正常触发索引:
SELECT * FROM schema.database.table where _id = 'b4dc8c1d-feb0-41ad-826b-55de1826d63f'
解决方案
1. 核对MongoDB索引的字段路径
- 确认索引的字段路径与Trino查询中的字段完全一致:你提到索引建在
genericEvent.header.transferReference,但文档和查询中实际字段是event.header.transferReference,路径不匹配会导致索引失效。 - 用MongoDB命令验证索引:
确保目标索引的键为db.table.getIndexes(){"event.header.transferReference": 1}(嵌套字段索引)或{"statusDate": 1}(日期字段索引)。
2. 保持字段类型匹配
- 对于
statusDate字段:文档中该字段是字符串类型,但Trino查询用了timestamp类型,类型不匹配会导致MongoDB无法使用索引。 - 修正方式二选一:
- 将MongoDB中的
statusDate转换为Date类型:db.table.updateMany({}, [{$set: {statusDate: {$toDate: "$statusDate"}}}]) - Trino查询时使用字符串匹配:
SELECT * FROM schema.database.table where statusDate = '2022-08-22T17:19:21.999'
- 将MongoDB中的
3. 检查Trino MongoDB连接器的索引下推配置
- 打开Trino的MongoDB连接器配置文件(
etc/catalog/mongodb.properties),确认以下配置已启用:
部分Trino版本中mongodb.pushdown-enabled=true mongodb.index-pushdown-enabled=truemongodb.index-pushdown-enabled默认未开启,需手动添加。
4. 手动定义Trino表结构,避免自动推断错误
- 执行计划中出现的
"genericevent"[2][3]数组索引形式,说明Trino自动推断schema时错误将嵌套文档识别为数组。 - 手动创建表结构,明确嵌套字段的类型:
手动定义后,Trino会正确生成嵌套字段的过滤表达式,让MongoDB可以匹配索引。CREATE TABLE schema.database.table ( _id VARCHAR, event ROW( status VARCHAR, header ROW( direction VARCHAR, receiver ROW(address VARCHAR), transferReference VARCHAR ) ), extractedFields ARRAY(ROW(field1 ARRAY(VARCHAR), field2 ARRAY(VARCHAR))), domainMetaData ROW(receivedTime TIMESTAMP), statusDate VARCHAR ) WITH ( connector = 'mongodb', collection = 'table' );
5. 在MongoDB端验证索引可用性
- 直接在MongoDB中执行查询并查看执行计划,确认索引是否能被正常使用:
如果MongoDB端也无法使用索引,优先解决MongoDB本身的索引问题(如路径错误、类型不匹配)。// 验证嵌套字段索引 db.table.find({"event.header.transferReference": "123"}).explain("executionStats") // 验证日期字段索引 db.table.find({"statusDate": "2022-08-22T17:19:21.999"}).explain("executionStats")
内容的提问来源于stack exchange,提问作者Tilak
相关产品推荐
相关产品推荐

