【问题标题】:Sqlite database optimizationSqlite 数据库优化
【发布时间】:2014-03-08 22:12:44
【问题描述】:

我有包含三个表的 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 条记录、document ~= 1000 条记录和 document_index ~= 500,000 条记录时,查询在我的 iPad 2 上执行大约 30 秒。

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

【问题讨论】:

  • 好吧,docuent.root_id 上的索引会直接跳出来,但我怀疑 Like 是你真正的问题。作为参数传入的内容(主要)

标签: sql sqlite sql-optimization


【解决方案1】:

我认为除了使用SQLite Full Text Search extension之外,没有任何实用的方法可以让您的查询更快地工作。

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

不幸的是,在 iOS 上默认情况下不启用 FTS,但显然如果您构建自己的应用程序和include your own copy of SQLite with FTS enabled,您仍然可以这样做。

【讨论】:

    【解决方案2】:

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

    1. dictionary.word 上没有索引,所以 SQLite 需要扫描完整的表
    2. 您正在使用 LIKE 运算符,它在大多数情况下无法使用索引。

    你的用例真的有必要使用 LIKE 查询而不是只检查字符串是否相等吗?

    【讨论】:

    • 我真的需要使用 LIKE,因为我需要通过子字符串进行比较。
    • @Alexander:如果您使用 LIKE 进行 prefix 匹配,那仍然绝对值得索引。 sqlite.org/optoverview.html#like_opt
    • 当您描述查询的确切外观时,我们可能会提出一些建议。但这需要一个单独的问题。
    【解决方案3】:

    尝试使用dictionary.word = @pQuery 而不是dictionary.word LIKE @pQuery

    运行“分析”

    【讨论】:

    • 不幸的是,我不能使用'equal',因为我需要通过子字符串进行比较。
    【解决方案4】:

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

    旧:

    dictionary.word LIKE 'prezident%'
    

    新:

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

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

    感谢大家的帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-11
      • 1970-01-01
      • 2012-09-07
      • 1970-01-01
      • 2013-12-14
      • 2012-10-01
      相关资源
      最近更新 更多