lol*_*ski 2 postgresql explain sql-execution-plan
explain analyze
显示 postgres 将对我的查询使用索引扫描,该查询获取行并按日期执行过滤(即2017-04-14 05:27:51.039
):
explain analyze select * from tbl t where updated > '2017-04-14 05:27:51.039';
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------
Index Scan using updated on tbl t (cost=0.43..7317.12 rows=10418 width=93) (actual time=0.011..0.515 rows=1179 loops=1)
Index Cond: (updated > '2017-04-14 05:27:51.039'::timestamp without time zone)
Planning time: 0.102 ms
Execution time: 0.720 ms
Run Code Online (Sandbox Code Playgroud)
但是运行相同的查询但使用不同的日期过滤器 '2016-04-14 05:27:51.039' 显示 postgres 将使用 seq scan 运行查询:
explain analyze select * from tbl t where updated > '2016-04-14 05:27:51.039';
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------
Seq Scan on tbl t (cost=0.00..176103.94 rows=5936959 width=93) (actual time=0.008..2005.455 rows=5871963 loops=1)
Filter: (updated > '2016-04-14 05:27:51.039'::timestamp without time zone)
Rows Removed by Filter: 947
Planning time: 0.100 ms
Execution time: 2910.086 ms
Run Code Online (Sandbox Code Playgroud)
postgres 如何决定使用什么,特别是在按日期执行过滤时?
Postgres 查询计划器的决策基于成本估计和列统计信息,这些信息ANALYZE
由其他一些实用程序命令收集并随机收集。这一切都在autovacuum
打开时自动发生(默认情况下)。
由于
WHERE
限制要检查的行的子句,大多数查询仅检索表中的一小部分行 。因此,规划器需要估计WHERE
子句的选择性,即与WHERE
子句中每个条件匹配的行的比例。用于此任务的信息存储在pg_statistic
系统目录中。inpg_statistic
中的条目由ANALYZE
和VACUUM ANALYZE
命令更新,并且即使在新更新时也始终是近似值。
有一个行数(in pg_class
),一个最常见值的列表等。
Postgres 期望找到的行越多,它就越有可能切换到顺序扫描,这样检索表的大部分内容会更便宜。
一般是索引扫描->位图索引扫描->顺序扫描,期望检索到的行数越多。
对于您的特定示例,重要的统计数据是histogram_bounds
,它让 Postgres 大致了解有多少行的值大于给定的行。pg_stats
人眼有更方便的视图:
SELECT histogram_bounds
FROM pg_stats
WHERE tablename = 'tbl'
AND attname = 'updated';
Run Code Online (Sandbox Code Playgroud)
手册中有专门的章节解释行估计。