【发布时间】:2021-10-03 02:48:49
【问题描述】:
这是我存储在 Calls 集合中的文档类型示例:
{
"_id" : "CL-33094E07D8C136ECA578",
"DateCreated" : ISODate("2019-03-30T16:27:55.605-04:00"),
"CallerIdNum" : "+19546543985",
"To" : "+13054595694",
"Status" : "STARTING",
"CallType" : "Incoming",
"Id_Account" : "1",
"HasRecording" : true,
"HasVoicemail" : true,
"Id_DID" : "PN6a7910b42f2ad4ce38946f451a24c2",
"IdTrunkOrigination" : "TK47546477f456b8be9b9f7faf46bc05",
"CallerIdNum_Reversed" : "58934564591+",
"To_Reversed" : "+13054595694"
}
我想为用户提供搜索特定电话的选项,因此我创建了此表单:
我不喜欢复合索引,因为我事先不知道有人想要搜索哪些字段。例如,某人可能对搜索具有语音邮件并且来自以 3885 结尾的电话号码的电话感兴趣。或者他们可能对获取由 DID 305-321-4388 收到的电话感兴趣并且有录音。 我该如何解决这个问题?有很多组合,创建那么多复合索引没有意义。
无论如何,由于有很多组合,我将表格分开,以便用户只能搜索来电和单独的表格去电。这样我确信我的所有查询都至少有这 3 个过滤器:
- Id 帐户 (Id_Account)
- 如果有来电,我们的去电 (CallType)
- 日期范围(创建日期)
因此,我创建了我的第一个复合索引,如下所示:
db.Calls.createIndex({Id_Account:1, CallType:1, DateCreated:1})
到目前为止,这有很大帮助,但如果您添加其他参数,查询仍需要一段时间才能执行。
由于创建复合索引的所有组合没有意义,我只想创建最有可能使用的组合的复合索引。例如,用户通常希望查找来自特定 DID 接收到的特定电话号码的电话呼叫。 DID 代表直接向内拨号,它是 AT&T 等提供商为您提供的电话号码,以便您接听电话。
所以现在我知道用户使用以下字段搜索呼叫是很常见的:
- Id_DID
- CallerIdNum_Reversed
我们使用 CallerIdNum_Reversed 以便查询可以更快地执行。我们在该字段上放置一个索引并搜索以某种模式开头的所有字段。因为有时来电显示号码带有+1,有时我们只是要求用户输入他有兴趣搜索的电话号码的最后一位。
因此,我创建了以下复合索引:
db.Calls.createIndex({Id_Account:1, CallType:1, DateCreated:1, Id_DID:1, CallerIdNum_Reversed:1 })
为什么下面这个查询需要 9 秒才能执行,即使我使用的是复合索引?
db.getCollection('Calls').find(
{
'Id_Account' : '11',
'CallType' : 'Incoming' ,
'DateCreated' : { '$gte': ISODate('2017-10-02T04:00:00Z') } , 'DateCreated' : { '$lte': ISODate('2021-10-03T04:59:59Z') } ,
'Id_DID' : '525552812424',
'CallerIdNum_Reversed' : /^3985/
}
)
【问题讨论】:
-
你试过解释吗? docs.mongodb.com/manual/tutorial/analyze-query-plan 另外我觉得您可以将 DateCreated 条件合并为一个...但是它不应该是查询 'DateCreated' 缓慢的原因:{ '$gte': ISODate('2017-10-02T04:00:00Z') ,'$lte': ISODate('2021-10-03T04:59:59Z') } ,
-
它检查 347,744 个键,并在查询末尾附加了 Explain("executionStats")。如果我按复合索引上的所有字段进行搜索,为什么它会检查这么多键?