【问题标题】:over - partition by in SQLite在 SQLite 中过度分区
【发布时间】:2018-01-23 20:38:22
【问题描述】:

我在 SQLite 数据库中有一个表 TABLE,其中包含 DATE、GROUP 列。我想选择每组中的前 10 个条目。在 stackoverflow 上研究了类似的主题后,我想出了以下查询,但运行速度非常慢。任何想法如何使它更快?

select * from TABLE as A 
where (select count(*) from TABLE as B 
       where B.DATE < A.DATE and A.GROUP == B.GROUP) < 10

这是 EXPLAIN QUERY PLAN (TABLE = clients_bets) 的结果:

【问题讨论】:

  • 显示该查询的表定义和EXPLAIN QUERY PLAN 的输出。
  • @CL 不完全确定表定义是什么意思,但除了 DATE 和 GROUP 之外,它还包含许多 (~50+) 列,DATE 是 TEXT,GROUP 是 INT。我将 EXPLAIN QUERY PLAN 的输出添加到问题中。
  • @JosefOndrej 你有关于 DATE 和 GROUP 的索引吗?为什么数据库必须对内部查询执行 SCAN?您无法避免外部完整扫描,因为您正在在过滤之前询问每一行的运行总计。
  • @PanagiotisKanavos 不,我在这些列上没有任何索引。现在,当我添加它们时,查询所需的时间减少了 10 倍,并且在 EXPLAIN QUERY PLAN 输出中,第三行现在是“SEARCH TABLE clients_bets AS B USING INDEX ...”

标签: sqlite


【解决方案1】:

这里有一些建议:

  • 使用覆盖索引(包含子查询中所需的所有数据的索引,在本例中为组和日期)

    create index some_index on some_table(some_group, some_date)
    
  • 另外,重写子查询以减少对外部查询的依赖:

    select * from some_table as A
    where rowid in (
        select B.rowid
        from some_table as B 
        where A.some_group == B.some_group 
        order by B.some_date limit 10 )
    

    查询计划更改自:

    0   0   0   SCAN TABLE some_table AS A
    0   0   0   EXECUTE CORRELATED LIST SUBQUERY 1
    1   0   0   SEARCH TABLE some_table AS B USING COVERING INDEX idx_1 (some_group=?)
    

    0   0   0   SCAN TABLE some_table AS A  
    0   0   0   EXECUTE CORRELATED SCALAR SUBQUERY 1
    1   0   0   SEARCH TABLE some_table AS B USING COVERING INDEX idx_1 (some_group=? AND some_date<?)
    

    虽然非常相似,但查询似乎要快得多。我不知道为什么。

【讨论】:

  • 覆盖索引有助于将时间进一步减少 7 倍,但是重写查询似乎不是一个好主意,因为它比我原来的建议慢 2 倍。
  • 有趣,在我的测试中它要快得多。另一个说明使用真实数据进行分析很重要的例子
猜你喜欢
  • 1970-01-01
  • 2023-02-09
  • 2021-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-19
  • 2019-10-01
  • 2017-10-28
相关资源
最近更新 更多