我有一张桌子(snmp陷阱,但那里既不存在也不存在)。
我有一个查询可以提取一些记录,如下所示:
SELECT *
FROM traps_trap
WHERE summary_id = 1600
ORDER BY traps_trap."trapTime";
这会立即响应,有6条记录。
当我添加LIMIT 50
时(因为并非所有结果都只有6条记录),它非常非常缓慢(至于根本不返回)。
summary_id
列上有一个索引,我只能假设它没有被用于第二个查询。
我知道解决此问题的工具是explain
,但我对它的理解结果不够熟悉。
解释分析第一个(快速)查询的详细信息如下:
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------------
Sort (cost=14491.51..14502.48 rows=4387 width=263) (actual time=0.128..0.130 rows=6 loops=1)
Output: id, summary_id, "trapTime", packet
Sort Key: traps_trap."trapTime"
Sort Method: quicksort Memory: 28kB
-> Index Scan using traps_trap_summary_id on public.traps_trap (cost=0.00..13683.62 rows=4387 width=263) (actual time=0.060..0.108 rows=6 loops=1)
Output: id, summary_id, "trapTime", packet
Index Cond: (traps_trap.summary_id = 1600)
Total runtime: 0.205 ms
(8 rows)
解释第二个是:
QUERY PLAN
---------------------------------------------------------------------------------------------------------
Limit (cost=0.00..2538.69 rows=10 width=263)
-> Index Scan using "traps_trap_trapTime" on traps_trap (cost=0.00..1113975.68 rows=4388 width=263)
Filter: (summary_id = 1600)
(3 rows)
我每天都会运行VACUUM
和ANALYZE
,我知道应该会改进计划。还有其他指针吗?
答案 0 :(得分:1)
使用trapTime的索引扫描比使用summary_id的索引扫描慢得多。 我会尝试嵌套查询(使用计划#1):
select * from (
SELECT *
FROM traps_trap
WHERE summary_id = 1600
ORDER BY traps_trap."trapTime"
) t
limit 50;
编辑:
在做了一些测试后,我了解到简单的查询嵌套(如上所述)对规划器没有影响。
要强制规划人员使用traps_trap_summary_id
索引,您可以使用CTE(我的测试确认此方法):
with t as (
SELECT *
FROM traps_trap
WHERE summary_id = 1600
ORDER BY traps_trap."trapTime"
)
select * from t
limit 50;