这是select语句:
SELECT COUNT(*) FROM object_detection_label where company_id = 'SOME_COMPANY_ID'
行数: 4700万
表格列:id,company_id,job_id,flight_plan_id,media_id,顶部,左侧,底部,右侧,置信度class_id,classes_version,display_id。
主键: ID
索引: company_id,job_id,flight_plan_id,media_id
结果来自:EXPLAIN ANALYZE SELECT * FROM object_detection_label where company_id = 'SOME_COMPANY_ID';
"Bitmap Heap Scan on object_detection_label (cost=41048.21..1042966.23 rows=614131 width=153) (actual time=62.563..216.589 rows=592653 loops=1)"
" Recheck Cond: ((company_id)::text = 'SOME_COMPANY_ID'::text)"
" Heap Blocks: exact=14303"
" -> Bitmap Index Scan on company_id_job_id_fp_id_media_id_idx (cost=0.00..40894.67 rows=614131 width=0) (actual time=60.170..60.170 rows=592653 loops=1)"
" Index Cond: ((company_id)::text = 'SOME_COMPANY_ID'::text)"
"Planning time: 0.061 ms"
"Execution time: 316.966 ms"
结果来自:EXPLAIN ANALYZE SELECT * FROM object_detection_label where company_id = 'SOME_COMPANY_ID' and job_id = 'SOME_JOB_ID';
"Index Scan using company_id_job_id_fp_id_media_id_idx on object_detection_label (cost=0.69..418.71 rows=102 width=153) (actual time=0.064..6.912 rows=13206 loops=1)"
" Index Cond: (((company_id)::text = 'CHURCH_OF_JESUS_CHRIST'::text) AND ((job_id)::text = '5cc085baa635404e54ebd46e'::text))"
"Planning time: 0.110 ms"
"Execution time: 10.114 ms"
请注意,它是在位子句的一部分使用位图热扫描,而不是索引扫描(如果我包含job_id,它将使用索引扫描)。
在仅将索引添加到company_id之后,它仍然没有使用索引扫描。为什么会这样呢?如何使用索引扫描?
答案 0 :(得分:2)
位图索引扫描 是一种索引扫描。
结果集是47000000行中的600万行,它们位于14000个块中。
这意味着使用正常的索引扫描,每个块将不得不被访问几次,这效率很低。位图索引扫描按顺序提取所需的表块,并且每个块仅提取一次。 PostgreSQL估计这会更有效,这可能是正确的。
您可以通过在设置后重新运行查询来验证这一点
SET enable_bitmapscan = off;