Ale*_*kii 6 postgresql index postgresql-9.3
我执行分页和,让我们说,行的排序products
表,使用上多列索引category
,score
和id
。
-- index
create index category_score_id on products(category, score, id)
where active = true;
-- selecting first page
select * from products where
category = 1
and active = true
order by score desc, id desc
limit 30;
-- selecting following pages
select * from products where
category = 1
and active = true
and (score, id) < (893, 102458) -- values from previous page
order by score desc, id desc
limit 30;
Run Code Online (Sandbox Code Playgroud)
仅使用索引扫描,就可以正常工作,并且符合预期:
-- explain analyze of 2-nd query:
Limit (cost=0.00..99.52 rows=30 width=2591) (actual time=0.090..0.179 rows=30 loops=1)
-> Index Scan Backward using category_score_id on products (cost=0.00..76435.07 rows=23041 width=2591) (actual time=0.089..0.172 rows=30 loops=1)
Index Cond: ((category = 1) AND (ROW(score, id) < ROW(893, 102458)))
Total runtime: 0.085 ms
Run Code Online (Sandbox Code Playgroud)
我很好奇的是为什么以下查询需要额外的 Bitmap Heap Scan:
-- explain analyze of 2-nd query:
Limit (cost=0.00..99.52 rows=30 width=2591) (actual time=0.090..0.179 rows=30 loops=1)
-> Index Scan Backward using category_score_id on products (cost=0.00..76435.07 rows=23041 width=2591) (actual time=0.089..0.172 rows=30 loops=1)
Index Cond: ((category = 1) AND (ROW(score, id) < ROW(893, 102458)))
Total runtime: 0.085 ms
Run Code Online (Sandbox Code Playgroud)
select count(*) from products where
category = 1
and active = true;
Run Code Online (Sandbox Code Playgroud)
它没有进行额外的位图扫描。它正在执行位图扫描而不是常规索引扫描。
为什么它要进行位图扫描?
因为它认为那样会更快。如果没有 LIMIT 和 ORDER BY,它预计使用位图扫描将使其以更有效的方式在表堆上执行 IO。您可以通过临时执行以下操作来查看 PostgreSQL 在此评估中是否正确set enable_bitmapscan TO off;
(尽管缓存效应可能会使该实验难以正确解释。)
另外,该行:
Rows Removed by Index Recheck: 93006
Run Code Online (Sandbox Code Playgroud)
建议您的 work_mem 设置可能太小而无法有效地容纳位图。
为什么它在解释计划中显示为两个条目而不是一个?
普通的索引扫描实际上是两个扫描合二为一,先扫描索引,然后嵌套查找表。但这两个部分是一体的,在执行计划中只作为一个条目出现。
位图案例也有这两个步骤,但是它们没有集成。可以在它们之间插入额外的步骤,例如 aBitmapOr
或 a BitmapAnd
。它将它们报告为两个单独的条目以适应这种可能性。
归档时间: |
|
查看次数: |
6436 次 |
最近记录: |