使用IN运算符查询域

时间:2018-01-04 16:02:45

标签: swift database performance realm

我可以从这些Realm查询中获得一些帮助。

数据库有超过400K的记录,“长度”和“密钥”都被编入索引。

使用以下查询过滤时(注意IN包含部分有大约40,000个随机唯一(无重复)元素,查询需要超过25秒

let predX = "length == 8 AND key IN {"acdghikl", "abfjlnop", "adefilno", ... " } 

但是,当我将相同的查询与其他具有彼此完全独立的记录的查询进行OR组合时,提取所需的时间会少得多,不到5秒。。 length6的记录集与长度为7的记录集不相交,与长度为8的记录集不相交

let predX = "length == 6 AND key IN {"uadhet", "nvawrt", "aqswdf", ... " }
let predY = "length == 7 AND key IN {"lmnzxiu", "bcruajs", "rokjuhy", ... " }
let predZ = "length == 8 AND key IN {"acdghikl", "abfjlnop", "adefilno", ... " }
let predCombined = NSCompoundPredicate(orPredicateWithSubpredicates: [predX, predY, predZ])

更新-编辑:

为了澄清,我目前的解决方案是简单地仅按长度获取记录,这需要少于0.05秒,将所有“键”添加到Set,并检查该组是否包含密钥。总时间平均为低于0.45秒,但如果我使用完整查询Realm with IN需要超过25秒

1)使用IN运算符完成查询:超过25秒

// about 40K keys in the IN containment
let predX = "length == 8 AND key IN {"acdghikl", "abfjlnop", "adefilno", ... " } " 
let result = realm.objects(XXX.self).filter(predX)
// result.count = 578

2)没有IN运算符的查询(0.05s)和Realm之外的过滤记录(~0.4s):总计低于0.45secs

let predX = "length == 8"
let result = realm.objects(XXX.self).filter(predX)
var filtered = [String]()
for record in result { // Over 50K records fetched
  if setOfKeys.contains(record.key) {
    filtered.append(record.key)
  }
}
// filtered.count = 578

1 个答案:

答案 0 :(得分:0)

Realm中的

IN并不是特别聪明或优化。在内部,x IN arr被翻译为x == arr[0] OR x == arr[1] OR ...。这给出了O(N*M)运行时,其中N是对象的数量,MIN子句中的值的数量。相比之下,使用setOfKeys进行手动过滤(假设为Set<String>)会提供O(N)O(N log M)运行时,对于大型M来说速度会快得多。

对我来说,为什么OR组合查询与不相交集合会使事情变得更快,这一点并不明显。