Sqlite数据库优化

时间:2013-01-04 08:40:47

标签: sql sqlite sql-optimization

我有三个表的sqlite3数据库:

CREATE TABLE document (
  id Int PRIMARY KEY NOT NULL,
  root_id Int,
  name Varchar(100),
  active Tinyint
);
CREATE INDEX IDX_documentId ON document (id);
CREATE INDEX IDX_documentName ON document (name);

CREATE TABLE dictionary (
  id Int PRIMARY KEY NOT NULL,
  word Varchar(100) NOT NULL
);
CREATE INDEX IDX_dictionaryId ON dictionary (id);
CREATE UNIQUE INDEX IDX_dictionaryWord ON dictionary (word ASC);

CREATE TABLE document_index (
  id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
  document_id Int NOT NULL,
  word_id Int NOT NULL,
  FOREIGN KEY(document_id) REFERENCES document(id),
  FOREIGN KEY(word_id) REFERENCES dictionary(id)
);
CREATE INDEX IDX_documentIndexId ON document_index (id);
CREATE INDEX IDX_documentIndexDocId ON document_index (document_id);
CREATE INDEX IDX_documentIndexWordId ON document_index (word_id);

我有sql脚本来选择包含字典中单词的所有文档:

SELECT document.id, document.name
FROM document
     INNER JOIN document_index on document_index.document_id=document.id
     INNER JOIN dictionary on dictionary.id=document_index.word_id
WHERE dictionary.word LIKE @pQuery
   AND document.active = 1
   AND document.root_id in (@pRoot1, @pRoot2, @pRoot3, @pRoot4, @pRoot5, @pRoot6, @pRoot7)

当字典包含〜= 400,000条记录,文档〜= 1000条记录和document_index~ = 500,000条记录时,查询在我的iPad 2上执行约30秒。

如何优化查询或更改数据库结构(例如添加索引)以减少查询时间?

4 个答案:

答案 0 :(得分:2)

除了使用SQLite Full Text Search extension之外,我认为除了使用include your own copy of SQLite with FTS enabled之外,还有任何实用的方法可以让您的查询更快。

FTS允许使用MATCH子句的快速版本,而不是本身慢LIKE

不幸的是,默认情况下,iOS上没有启用FTS,但显然,如果您构建自己的应用程序{{3}},仍然可以执行此操作。

答案 1 :(得分:2)

瓶颈很可能是WHERE dictionary.word LIKE @pQuery部分。

  1. 你没有关于dictionary.word的索引,所以SQLite需要扫描完整的表
  2. 您正在使用LIKE运算符,在大多数情况下不能使用索引。
  3. 您的用例是否真的需要使用LIKE查询而不仅仅是检查字符串是否相等?

答案 2 :(得分:0)

尝试使用dictionary.word = @pQuery代替dictionary.word LIKE @pQuery

运行“分析”

答案 3 :(得分:0)

我找到了解决方案。这个解决方案提高了查询执行速度60!倍。我发现它here更详细 - here。这很简单,我将LIKE表达式替换为比较> =和<:

旧:

dictionary.word LIKE 'prezident%'

新:

dictionary.word >= 'prezident' AND dictionary.word < 'prezidentz' /* Added z to the second string*/ 

这个解决方案有一个限制,我可以通过字符串的一部分查找,但是在字符串ony的末尾,即'expr%'。

谢谢大家的帮助!