【问题标题】:Slow Sqlite Select behaviour when trying to select several rows尝试选择多行时,Sqlite Select 行为缓慢
【发布时间】:2020-07-13 07:03:54
【问题描述】:

我的 sqlite 数据库 t1 和 t2 中有两个表。 t1 有两列 a 和 b。 t2 有一列与 t1 中的相同。我已经为两个表中的每一列都建立了索引。我想从表 t1 中选择所有行,其中 t1.a 存在于表 t2 中。所以我写了一个查询:

select t1.a, t1.b from t1 where t1.a in(select t2.a from t2) limit 10000000;

我使用限制来选择所有行,而不是前 100 行。

表 t1 包含 6 000 000 行,表 t2 包含 100 000 行。此查询执行 1400 毫秒。

但是当我尝试使用此查询仅选择 t1.a 时:

select t1.a from t1 where t1.a in(select t2.a from t2) limit 10000000;

只用了 86 毫秒。

解释查询计划:

SEARCH TABLE csv USING COVERING INDEX iin_idx (iin=?)
USING INDEX sqlite_autoindex_input_1 FOR IN-OPERATOR

问题:

  1. 为什么 sqlite 会这样?
  2. 选择一列或多列有什么区别?
  3. 是否可以加快查询速度?
  4. 为什么 sqlite 使用自动索引而不是创建一个?

我想用 155 000 000 行填充 t1 表,因此查询时间会显着增加。

【问题讨论】:

  • 您不需要 LIMIT 来选择所有行。
  • 显然您正在使用 CSV 文件? b列包含什么?它比 a 包含的列大得多吗?
  • 您是否按顺序运行了一次查询?如果是这样,请再次尝试第一个。它可能只是磁盘缓存。
  • 请创建一个minimal reproducible example,让我们能够观察到相同的行为。
  • @mkrieger1 否,a 列是 12 个符号,b 列是 11 个符号。

标签: database sqlite select


【解决方案1】:

一种可能性是disk caching。从磁盘读取速度很慢,特别是如果您有hard disk drive (HDD) 而不是solid-state drive (SSD) 第一次运行查询时,缓存是“冷”的,数据必须从磁盘加载到内存中。第二次运行查询时,数据已经缓存在内存中,速度会快得多。

尝试运行查询几次,看看性能是否发生变化。

【讨论】:

  • 我注意到缓存。我已经在冷数据库上运行了所有查询。我还有一个 SSD 磁盘。
  • @pingvincible 那么下一个可能就是t1.b比t1.a大很多,as mkrieger1 suggested
【解决方案2】:

我想我找到了解决办法!我创建了一个额外的索引:

create index if not exists ab_b_idx on t1(a, b);

之后,同时选择 a 和 b 列的运行速度与只选择一列一样快。

我在文档中找到的这种行为的解释 Covering indices:

但是,如果要从表中提取的所有列都已在索引本身中可用,则 SQLite 将使用索引中包含的值,并且永远不会查找原始表行。这为每一行节省了一次二分搜索,并且可以使许多查询的运行速度提高一倍。

更新:在表 t1 中搜索 100 000 000 行花费了 550 毫秒。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-15
    • 2013-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-11
    相关资源
    最近更新 更多