sqlite - SQLite改进大小写和按性能分组

标签 sqlite group-by case-when

我正在使用SQLite3优化查询。
有一些“ CASE WHEN”,“ GROUP BY”,“ COUNT”功能。

但是查询非常慢(大约14秒)

这是我的数据库文件信息。



大小:约2GB
行:约300万
列:55列



我该如何优化查询的性能?

是否有更好的查询结果?

请帮助我TT谢谢。

select
  case
    when score = 100 then 'A'
    when score < 100 and score >= 40 then 'B'
    else 'C'
  end as range,
  count(*) as count
from grade_info
where type < 9 and 
   (date >= '2019-07-09 00:00:00' and date <= '2019-07-09 23:59:59') and 
   is_new = 1
group by
  case
    when score = 100 then 'A'
    when score < 100 and score >= 40 then 'B'
    else 'C'
  end;


grade_info具有多列索引:(type, date, is_new, score)

在此查询中始终使用列的条件(类型,日期,is_new)。这是解释查询计划的结果。

 selectid | order | from | detail
 --------------------------------
 0          0       0      SEARCH TABLE grade_info USING INDEX idx_03 (type<?) (~2777 rows) 
 0          0       0      USE TEMP B-TREE FOR GROUP BY 


我想要这样的结果。

A | 5124
B | 124
C | 12354

最佳答案

如Shawn建议的那样,尝试更改索引以将date列作为第一列:

CREATE INDEX [idx_cover] ON [grade_info] ([date], [is_new], [type], [score]);

sqlite允许在WHERE和GROUP BY子句中引用别名表达式,因此您可以简单地说GROUP BY range而不是重复CASE语句。这可能不会改变效率,但是会使查询更短且更具可读性。
如果按照MikeT的建议运行ANALYZE,则执行计划应更改为“ COVERING INDEX ...”。如果我理解正确,则表明可以通过遍历单个多列索引来执行整个查询,而无需返回表数据。
尝试日期BETWEEN '2019-07-09 00:00:00' AND '2019-07-09 23:59:59'
最后,CASE ... WHEN发生短路,因此请确保首先放置更可能的情况,以避免不必要的计算。同时消除多余的条件检查。如果您已经在上一个条件中检查了某个范围,则无需在下一个条件中重新评估该范围。 (如果您已经排除了分数= 100,那么就不必检查分数<100,因为它当然会小于100 ...假设所有分数都确保在0到100之间)。例如,如果分数是均匀分布的,则后续操作可能会更快,可能会消除+17000个条件检查。


SELECT
  CASE
    WHEN score < 40 then 'C'
    WHEN score < 100 then 'B'  -- already tested to be >= 40
    ELSE 'A'                   -- already tested to be >= 100
  END AS range,
  count(*) AS count
FROM grade_info
WHERE type < 9 AND
      (date BETWEEN '2019-07-09 00:00:00' AND '2019-07-09 23:59:59') AND
      is_new = 1       
GROUP BY
  range;

关于sqlite - SQLite改进大小写和按性能分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56962763/

相关文章:

sqlite 选择查询

sql - 从 sqlite 数据库中选择不同的一对值

mysql - 查询中的两个分组,其中一个没有聚合函数。

sql - 按日期范围分组 (teradata)

php - php 页面中的查询不起作用

sql - Oracle SQL CASE WHEN ORA-00932 : inconsistent datatypes: expected CHAR got NUMBER 00932. 00000 - "inconsistent datatypes: expected %s got %s"

c# - 用于 sqlite 的 oledb 提供程序

Laravel 迁移创建用户 "unexpected ' use' (T_USE)"SQLite

mysql - 按时间戳字段的日期部分分组

sql - 如何防止将大数字转换为 varchar 示例 1444092 是 1.44409e+006