Postgres ORDER BY 索引列提高了查询的性能
Postgres ORDER BY indexed column increases performance of the query
我有一个包含 2 列的 table notification
:id
(主键)和 entity
(jsonb)
SELECT *
FROM notification
WHERE entity -> 'name' = 'Hello World'
ORDER by id DESC
执行速度比没有 ORDER BY
:
的相同查询快得多
SELECT *
FROM notification
WHERE entity -> 'name' = 'Hello World'
没有实体 -> 'name' 索引。
我注意到,第一个查询使用索引扫描,而第二个查询使用序列扫描。执行时间的差异:60 秒 vs 0.5 秒
- table中的行数:16696
- 返回结果:95行
怎么解释呢?
更新。 EXPLAIN (ANALYZE, BUFFERS) 第一个查询:
Index Scan using notification_pkey on notification (cost=0.41..233277.12 rows=1 width=264) (actual time=480.582..583.623 rows=95 loops=1)
Filter: ((entity ->> 'name'::text) = 'Hello World'::text)
Rows Removed by Filter: 16606
Buffers: shared hit=96807
Planning Time: 0.211 ms
Execution Time: 583.826 ms
对于第二个查询:
Seq Scan on notification (cost=0.00..502145.78 rows=1 width=264) (actual time=49675.453..60160.280 rows=95 loops=1)
Filter: ((entity ->> 'name'::text) = 'Hello World'::text)
Rows Removed by Filter: 16606
Buffers: shared hit=91608 read=497908
I/O Timings: read=55311.842
Planning Time: 0.112 ms
Execution Time: 60160.309 ms
UPD 2. 我在 table 上执行了 VACUUM ANALYZE,但它并没有提高性能。
您的 table 似乎膨胀到包含近 500000 个 8kB 空块的程度。由于在索引扫描期间不读取这些内容,因此索引扫描实际上比顺序扫描更快。
您应该找到并解决导致膨胀的问题,然后花点时间用
重新组织table
VACUUM (FULL) notification;
我有一个包含 2 列的 table notification
:id
(主键)和 entity
(jsonb)
SELECT *
FROM notification
WHERE entity -> 'name' = 'Hello World'
ORDER by id DESC
执行速度比没有 ORDER BY
:
SELECT *
FROM notification
WHERE entity -> 'name' = 'Hello World'
没有实体 -> 'name' 索引。
我注意到,第一个查询使用索引扫描,而第二个查询使用序列扫描。执行时间的差异:60 秒 vs 0.5 秒
- table中的行数:16696
- 返回结果:95行
怎么解释呢?
更新。 EXPLAIN (ANALYZE, BUFFERS) 第一个查询:
Index Scan using notification_pkey on notification (cost=0.41..233277.12 rows=1 width=264) (actual time=480.582..583.623 rows=95 loops=1)
Filter: ((entity ->> 'name'::text) = 'Hello World'::text)
Rows Removed by Filter: 16606
Buffers: shared hit=96807
Planning Time: 0.211 ms
Execution Time: 583.826 ms
对于第二个查询:
Seq Scan on notification (cost=0.00..502145.78 rows=1 width=264) (actual time=49675.453..60160.280 rows=95 loops=1)
Filter: ((entity ->> 'name'::text) = 'Hello World'::text)
Rows Removed by Filter: 16606
Buffers: shared hit=91608 read=497908
I/O Timings: read=55311.842
Planning Time: 0.112 ms
Execution Time: 60160.309 ms
UPD 2. 我在 table 上执行了 VACUUM ANALYZE,但它并没有提高性能。
您的 table 似乎膨胀到包含近 500000 个 8kB 空块的程度。由于在索引扫描期间不读取这些内容,因此索引扫描实际上比顺序扫描更快。
您应该找到并解决导致膨胀的问题,然后花点时间用
重新组织tableVACUUM (FULL) notification;