【发布时间】:2016-02-02 17:00:20
【问题描述】:
假设有一个具有以下架构的作业运行历史记录表:
job_runs
(
run_id integer not null, -- identifier of the run
job_id integer not null, -- identifier of the job
run_number integer not null, -- job run number, run numbers increment for each job
status text not null, -- status of the run (running, completed, killed, ...)
primary key (run_id)
-- ...
)
并且每个作业都需要使用status != 'running' 获得最后10 次运行(作业因job_id 而不同)。为此,我编写了以下查询:
SELECT
*
FROM
job_runs AS JR1
WHERE
JR1.run_number IN
(
SELECT
JR2.run_number
FROM
job_runs AS JR2
WHERE
JR2.job_id = JR1.job_id
AND
JR2.status != 'running'
ORDER BY
JR2.run_number
DESC
LIMIT
10
)
它可以满足我的需要,但即使在 job_runs 表的 job_id 和 run_num 字段上有一个多字段索引,查询也很慢,因为它会扫描 job_runs 表,并且它的每一行都运行子查询.索引每次都能帮助子查询快速运行,但嵌套查询扫描整个表的事实会降低性能。那么如何调整查询的性能呢?
一些想法:
作业数量(不同的job_ids)很少,如果 SQLite 中有 FOR 循环,则很容易遍历所有不同的 job_ids 并运行子查询
传递作业 ID 而不是 JR1.job_id 然后 UNION 所有结果。
重要:
请不要建议在我的应用程序的源代码中运行循环。我需要纯 SQL 解决方案。
【问题讨论】:
-
我认为你不走运。 This has been asked before 他们想出了你的解决方案。 SQLite 非常有限,尝试在其中做所有事情并不总是最好的选择。为什么需要纯 SQL 解决方案?
-
你可能想试试dba.stackexchange.com。
-
@Schwern 感谢 dba.stackexchange.com,顺便说一句,有没有办法解决这个问题? “纯 SQL 解决方案”呢,是应用程序设计的问题。
-
如果你的应用程序被设计成所有数据查询都必须 100% 在 SQLite 中执行,那么你就有一个严重的设计问题。 SQLite 不够灵活。你会再次遇到这个问题。我建议您切换数据库或更改您的应用程序设计。
-
不,@Schwern 并非如此。
标签: performance sqlite select