我知道使用EXPLAIN ANALYZE我可以得到预计的成本和实际执行时间(它们是不同的单位,啊!),但有没有办法让Postgres告诉我它需要做多少I/O(逻辑或物理)来满足查询?有没有办法让postgres显示实际的I/O查询
(我在寻找相当于“组统计木卫一”为Sybase或MS SQL Server)。
我知道使用EXPLAIN ANALYZE我可以得到预计的成本和实际执行时间(它们是不同的单位,啊!),但有没有办法让Postgres告诉我它需要做多少I/O(逻辑或物理)来满足查询?有没有办法让postgres显示实际的I/O查询
(我在寻找相当于“组统计木卫一”为Sybase或MS SQL Server)。
在PostgreSQL的9.0开始,你可以执行:
EXPLAIN (ANALYZE ON, BUFFERS ON) SELECT ...
,它会告诉你该语句与PostgreSQL的缓存如何相互作用。在报告缓存未命中的情况下,这将是一次操作系统调用以读取某些内容。你不能确定这是一个物理I/O,因为它可能在OS缓存中。但这可能更像你在这里寻找的东西,而不是试图查看pg_stat_ *信息。
有没有什么简单的SET STATISTICS IO ON
为PostgreSQL
,很遗憾。但是,通过pg_statio_*
系统目录可以获得IO统计信息。这并不完美,因为数据不在会话范围内,但如果您希望查看高效查询的效果并处于无尘室环境,那么对于大多数问题来说,这种方法足够好。
http://www.postgresql.org/docs/current/static/monitoring-stats.html
不是真的如PostgreSQL的也很大程度上依赖于操作系统的缓存,它没有办法知道发生了什么事情在那里的方式。 pg_catalog中的pg_statio *系列视图保持运行计数的命中和实际读取,但这些读取可能已经命中了操作系统缓存。
这个答案是没有直接关系到一个特定的查询语句,但对于帮助那些谁寻求呈现出“磁盘缓存VS”的方式,当在这里结束:
-- perform a "select pg_stat_reset();" when you want to reset counter statistics
with
all_tables as
(
SELECT *
FROM (
SELECT 'all'::text as table_name,
sum((coalesce(heap_blks_read,0) + coalesce(idx_blks_read,0) + coalesce(toast_blks_read,0) + coalesce(tidx_blks_read,0))) as from_disk,
sum((coalesce(heap_blks_hit,0) + coalesce(idx_blks_hit,0) + coalesce(toast_blks_hit,0) + coalesce(tidx_blks_hit,0)) ) as from_cache
FROM pg_statio_all_tables --> change to pg_statio_USER_tables if you want to check only user tables (excluding postgres's own tables)
) a
WHERE (from_disk + from_cache) > 0 -- discard tables without hits
),
tables as
(
SELECT *
FROM (
SELECT relname as table_name,
((coalesce(heap_blks_read,0) + coalesce(idx_blks_read,0) + coalesce(toast_blks_read,0) + coalesce(tidx_blks_read,0))) as from_disk,
((coalesce(heap_blks_hit,0) + coalesce(idx_blks_hit,0) + coalesce(toast_blks_hit,0) + coalesce(tidx_blks_hit,0)) ) as from_cache
FROM pg_statio_all_tables --> change to pg_statio_USER_tables if you want to check only user tables (excluding postgres's own tables)
) a
WHERE (from_disk + from_cache) > 0 -- discard tables without hits
)
SELECT table_name as "table name",
from_disk as "disk hits",
round((from_disk::numeric/(from_disk + from_cache)::numeric)*100.0,2) as "% disk hits",
round((from_cache::numeric/(from_disk + from_cache)::numeric)*100.0,2) as "% cache hits",
(from_disk + from_cache) as "total hits"
FROM (SELECT * FROM all_tables UNION ALL SELECT * FROM tables) a
ORDER BY (case when table_name = 'all' then 0 else 1 end), from_disk desc