我有一个包含28列和7M记录的表,没有主键。
CREATE TABLE records (
direction smallint,
exporters_id integer,
time_stamp integer
...
)
我在此表和真空表上创建索引(autovacuum打开)
CREATE INDEX exporter_dir_time_only_index ON sacopre_records
USING btree (exporters_id, direction, time_stamp);
我希望执行此查询
SELECT count(exporters_id) FROM records WHERE exporters_id = 50
该表有6982224条记录,其中exporters_id = 50.我希望此查询使用仅索引扫描来获取结果,但它使用顺序扫描。 这是“EXPLAIN ANALYZE”输出:
Aggregate (cost=204562.25..204562.26 rows=1 width=4) (actual time=1521.862..1521.862 rows=1 loops=1)
-> Seq Scan on sacopre_records (cost=0.00..187106.88 rows=6982149 width=4) (actual time=0.885..1216.211 rows=6982224 loops=1)
Filter: (exporters_id = 50)
Rows Removed by Filter: 2663
Total runtime: 1521.886 ms
但是当我将exporters_id更改为另一个id时,查询使用仅索引扫描
Aggregate (cost=46.05..46.06 rows=1 width=4) (actual time=0.321..0.321 rows=1 loops=1)
-> Index Only Scan using exporter_dir_time_only_index on sacopre_records (cost=0.43..42.85 rows=1281 width=4) (actual time=0.313..0.315 rows=4 loops=1)
Index Cond: (exporters_id = 47)
Heap Fetches: 0
Total runtime: 0.358 ms
问题出在哪里?
答案 0 :(得分:4)
解释告诉你原因。仔细观察。
Aggregate (cost=204562.25..204562.26 rows=1 width=4) (actual time=1521.862..1521.862 rows=1 loops=1)
-> Seq Scan on sacopre_records (cost=0.00..187106.88 rows=6982149 width=4) (actual time=0.885..1216.211 rows=6982224 loops=1)
Filter: (exporters_id = 50)
Rows Removed by Filter: 2663
Total runtime: 1521.886 ms
您的过滤器只删除了表中6982149行总数中的2663行,因此执行顺序扫描应该比使用索引更快,因为磁盘头应该通过6982149 - 2663 = 6979486记录。磁头开始按顺序读取整个表,并且正在移除与您的条件不匹配的小部分(0.000004%)。在索引扫描的情况下,它应该从索引文件跳转并返回到数据文件6979486次,这肯定应该比你现在获得的这些1.5秒慢!