【问题标题】:How can I optimize SQLite ORDER BY rowid?如何优化 SQLite ORDER BY rowid?
【发布时间】:2014-08-03 00:57:00
【问题描述】:

我想在我的 sqlite 数据库中查询所有大于 20 的“级别”值,将结果限制为 100 并按 rowid 排序。

当按 rowid 排序时,查询要慢得多。该数据库包含约 300 万条记录 level的最大值为50。为level创建一个索引。

这个语句需要大约 20 毫秒:

SELECT * FROM log WHERE level > 20 LIMIT 100

这条语句需要大约 100 毫秒:

SELECT * FROM log WHERE level > 20 ORDER BY rowid LIMIT 100

此语句耗时约 1000 毫秒(不存在级别值大于 50 的行):

SELECT * FROM log WHERE level > 50 ORDER BY rowid LIMIT 100

有没有办法对此进行优化以加快 ORDER BY 查询?

这是使用的索引:

CREATE INDEX level_idx ON table (level)

【问题讨论】:

  • 你有索引吗?
  • 我会检查索引及其碎片,我会尝试读取未提交的内容,更新统计信息,并将列限制为仅需要的列。
  • 嗨,CL,我更新了这个问题。我在级别上使用索引。

标签: sql sqlite sorting


【解决方案1】:

有两种可能的方法来执行这个查询:

  1. level_idx 索引中搜索level>20 的第一个条目,然后扫描所有以下条目并从表中获取每个对应的行。 因为索引条目不是按rowid 顺序存储的,所以必须对所有结果进行排序。 然后可以返回其中的前 100 个。

  2. 忽略索引。 扫描表的所有行(已按rowid 顺序存储),并返回与level 列匹配的任何行。

数据库估计第二种方法更快。

如果您估计第一种方法更快,即只有很少的行与level 过滤器匹配,以至于在扫描表时获取和排序剩余行比忽略不匹配的行更快,那么您可以强制数据库使用带有 INDEXED BY 子句的索引:

SELECT *
FROM log INDEXED BY level_idx
WHERE level > 20
ORDER BY rowid
LIMIT 100

但是,如果您自己的估计错误,强制索引可能会导致严重的减速。

【讨论】:

  • 谢谢 CL!第二种情况的新值是~20ms,第三种情况是~15ms。这确实成功了。
  • 检查最坏的情况:level > -1 有什么区别?
  • 你是对的,我认为你的猜测是检查会很慢。对于级别 > -1,时间为 8.5 秒...当我从查询中删除显式 INDEXED BY 时,时间回到 ~25 毫秒。这是为什么呢?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-31
  • 2011-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多