Sqlite улучшить случай-когда и группировать по производительности - PullRequest
2 голосов
/ 10 июля 2019

Я оптимизирую свой запрос, используя SQLite3.Есть несколько функций «CASE WHEN», «GROUP BY», «COUNT».

НО запрос ОЧЕНЬ медленный (около 14 секунд)

Вот информация о моем файле базы данных.

  1. размер: около 2 ГБ
  2. строк: около 3 миллионов
  3. столбцов: 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 имеет несколько столбцовindex: (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

1 Ответ

1 голос
/ 10 июля 2019
  • Как предлагает Шон, попробуйте изменить индекс, чтобы столбец date был первым столбцом:

    CREATE INDEX [idx_cover] ON [grade_info] ([date], [is_new], [type], [score]);
    
  • sqlite позволяет ссылаться на псевдонимы.в предложениях WHERE и GROUP BY, поэтому вы можете просто сказать GROUP BY range вместо того, чтобы повторять оператор CASE.Это, вероятно, не изменит эффективность, но сделает запрос короче и более читабельным.

  • Если вы запустите ANALYZE, как рекомендует MikeT, план выполнения должен измениться на «ИНДЕКС ПОКРЫТИЯ»... ".Если я правильно понимаю, это означает, что весь запрос может быть выполнен путем обхода одного индекса из нескольких столбцов без возврата к данным таблицы.

  • Дата попытки BETWEEN '2019-07-09 00:00:00' AND '2019-07-09 23:59:59'.

  • Наконец, CASE ... КОГДА короткое замыкание, поэтому сначала убедитесь, что наиболее вероятные случаи указаны так, чтобы избежать ненужных вычислений.Также исключите избыточные условные проверки.Если вы уже проверили определенный диапазон в предыдущем условии, нет необходимости переоценивать этот диапазон в следующем условии.(Если вы уже исключили балл = 100, то нет необходимости проверять балл <100, поскольку он, конечно, будет меньше 100 ... при условии, что все баллы находятся в диапазоне от 0 до 100). Например,если результаты распределены равномерно, то следующее может быть быстрее, возможно, устраняя +17000 условных проверок. </p>

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;
...