SQLite - 帮助使复杂查询更高效

时间:2014-03-13 17:35:20

标签: sqlite performance

数据是以桶形式构建的财务数据,其中一个存储桶(Rollup)可以包含其他数据桶。作为示例结构:

Rollup1 | Dept1
Rollup1 | Rollup2 | Dept2
Rollup1 | Rollup2 | Dept3
Rollup1 | Rollup3 | Dept4
Rollup1 | Rollup3 | Rollup4 | Dept5
Rollup1 | Rollup3 | Rollup4 | Dept6

这里有8个列,其中分布着Rollups和Depts(但是叶子总是单个Depts)。大约10k行。

查询结果的目标是显示包含所有汇总的单个列,具有可变逻辑以正常显示某些汇总,并修改所有其他汇总。

例如,如果我的变量包含“Dept4”,我的结果将是:

Rollup1
Rollup3
NA - Rollup2
NA - Rollup4

在实际情况中,有3个变量决定了Rollup列的显示。

这是我拥有的,它应该发挥作用,但是,性能非常糟糕。 1查询最多需要5秒,我想改进。

SELECT DISTINCT CASE
   WHEN "2" NOT IN
      (
         SELECT "2"
         FROM "Finance New"
         WHERE (@VAR3 = 'All' OR @VAR3 IN ("2","3","4","5","6","7","8","9"))
         AND (@VAR4 = 'All' OR "10" = @VAR4)
         AND (@VAR5 = 'All' OR "11" = @VAR5)
         )
   THEN
      'Z N/A - ' || "2"
   ELSE
      "2"
   END AS COL2
FROM "Finance New"
WHERE "5" <> 'All Applicable' AND "1" <> '9999'
AND "2" LIKE '9%'

UNION

SELECT DISTINCT CASE
   WHEN "3" NOT IN
      (
         SELECT "3"
         FROM "Finance New"
         WHERE (@VAR3 = 'All' OR @VAR3 IN ("2","3","4","5","6","7","8","9"))
         AND (@VAR4 = 'All' OR "10" = @VAR4)
         AND (@VAR5 = 'All' OR "11" = @VAR5)
         )
   THEN
      'Z N/A - ' || "3"
   ELSE
      "3"
   END AS COL2
FROM "Finance New"
WHERE "5" <> 'All Applicable' AND "1" <> '9999'
AND "3" LIKE '9%'
UNION

Etc, for each of the columns in the Rollup/Dept Tree report.

每个联合查询中的内部选择根据变量条件附加到文本。排序是自动完成的。 UNION(AND "3" LIKE "9%")之前的最后一行是实际获取Rollup。汇总全部以9开头。

输入参数标记为@VARx。

我想知道是否有更有效的方法来执行此操作,假设我无法创建临时表并且无法更改数据的结构。

谢谢!

1 个答案:

答案 0 :(得分:1)

  1. 所有这些OR都阻止了索引的使用。 如果可能的话,删除那些@VAR = 'All'比较(或另一个)并动态创建SQL字符串,具体取决于实际的VAR3 / 4/5值。
  2. LIKE阻止使用索引(因为LIKE(或GLOB)在索引列上需要TEXT亲和力)。 将其替换为正常比较,即将"col" LIKE '9%'替换为"col" >= '9' AND "col" < ':'
  3. UNION已删除重复项;删除DISTINCT。
  4. 如果没有索引,所有这些查询都会执行全表扫描。 创建以下(覆盖)索引:
  5.     CREATE INDEX i_10_11_all on "Finance New"("10","11", "2","3","4","5","6","7","8","9");
        CREATE INDEX i_11_10_all on "Finance New"("11","10", "2","3","4","5","6","7","8","9");
        CREATE INDEX i_2_1_5 on "Finance New"("2", "1","5");
        CREATE INDEX i_3_1_5 on "Finance New"("3", "1","5");
        -- and so on for 4..9