在文本中搜索匹配的单词时,我可以优化核心数据查询吗? (这个问题也涉及到 iPhone 上自定义 SQL 与 Core Data 的区别。)
我正在开发一款新的 (iPhone) 应用程序,它是科学数据库的手持引用工具。主界面是一个标准的可搜索表格 View ,我希望在用户输入新单词时得到即时响应。单词匹配必须是文本中单词的前缀。该文本由 100,000 个单词组成。
在我的原型(prototype)中,我直接编写了 SQL 代码。我创建了一个单独的“单词”表,其中包含主实体文本字段中的每个单词。我对单词进行了索引并按照以下方式执行了搜索
SELECT id, * FROM textTable
JOIN (SELECT DISTINCT textTableId FROM words
WHERE word BETWEEN 'foo' AND 'fooz' )
ON id=textTableId
LIMIT 50
这运行得非常快。使用 IN 可能也同样有效,即
SELECT * FROM textTable
WHERE id IN (SELECT textTableId FROM words
WHERE word BETWEEN 'foo' AND 'fooz' )
LIMIT 50
LIMIT 至关重要,它可以让我快速显示结果。我通知用户,如果达到限制,则显示太多。这很糟糕。
过去几天我一直在思考迁移到核心数据的优势,但我担心重要查询的架构、索引和查询缺乏控制。
理论上,textField MATCHES '.*\bfoo.*'
的 NSPredicate 就可以工作,但我确信它会很慢。这种文本搜索似乎很常见,我想知道通常的攻击是什么?您会像我上面那样创建一个单词实体并使用“word BEGINSWITH 'foo'”谓词吗?它会像我的原型(prototype)一样快吗? Core Data 会自动创建正确的索引吗?我找不到任何明确的方法来向持久存储提供有关索引的建议。
我在我的 iPhone 应用程序中看到了 Core Data 的一些很好的优势。故障和其他内存考虑因素允许对 TableView 查询进行高效的数据库检索,而无需设置任意限制。对象图管理使我能够轻松遍历实体,而无需编写大量 SQL。将来迁移功能会很好。另一方面,在有限的资源环境(iPhone)中,我担心自动生成的数据库会因为元数据、不必要的逆关系、低效的属性数据类型等而变得臃肿。
我应该一头扎进去还是谨慎行事?
最佳答案
我制定了一个解决方案。我认为它类似于 this post 。我将合并源代码添加到我的 Core Data 项目中,然后创建一个不是托管对象子类的全文搜索类。在FTS类中,我#import "sqlite3.h"
(源文件)而不是sqlite框架。 FTS 类保存到与 Core Data 持久存储不同的 .sqlite 文件。
当我导入数据时,Core Data 对象将相关 FTS 对象的 rowid 存储为整数属性。我有一个静态数据集,因此我不担心引用完整性,但维护完整性的代码应该很简单。
为了执行 FTS,我 MATCH
查询 FTS 类,返回一组 rowid。在我的托管对象类中,我使用 [NSPredicate predicateWithFormat:@"rowid IN %@", rowids]
查询相应的对象。我避免以这种方式遍历任何多对多关系。
性能提升非常显着。我的数据集有 142287 行,包括 194MB(核心数据)和 92MB(删除停用词的 FTS)。根据搜索词频率的不同,我的搜索时间从几秒缩短到 0.1 秒(对于不常见术语(<100 次点击))和 0.2 秒(对于频繁术语(>2000 次点击))。
我确信我的方法存在无数问题(代码膨胀、可能的命名空间冲突、丢失一些核心数据功能),但它似乎有效。
关于iphone - 如何优化全文搜索的 Core Data 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1774369/