我运行此查询以检查我的DataBase中是否存在一些未使用的索引。
select
t.tablename AS "relation",
indexname,
c.reltuples AS num_rows,
pg_relation_size(quote_ident(t.tablename)::text) AS table_size,
pg_relation_size(quote_ident(indexrelname)::text) AS index_size,
idx_scan AS number_of_scans,
idx_tup_read AS tuples_read,
idx_tup_fetch AS tuples_fetched
FROM pg_tables t
LEFT OUTER JOIN pg_class c ON t.tablename=c.relname
LEFT OUTER JOIN
( SELECT c.relname AS ctablename, ipg.relname AS indexname, x.indnatts AS number_of_columns, psai.idx_scan, idx_tup_read, idx_tup_fetch, indexrelname, indisunique FROM pg_index x
JOIN pg_class c ON c.oid = x.indrelid
JOIN pg_class ipg ON ipg.oid = x.indexrelid
JOIN pg_stat_all_indexes psai ON x.indexrelid = psai.indexrelid )
AS foo
ON t.tablename = foo.ctablename
WHERE t.schemaname='public'
and idx_scan = 0
ORDER BY
--1,2
--6
5 desc
;
我有很多行,这些字段都是零:
number_of_scans,
tuples_read,
tuples_fetched
这是否意味着我可以放弃它们?元数据是否有可能过时?我怎么检查呢?
我使用版本9.6的Postgres
答案 0 :(得分:2)
您的查询错过了一些不需要扫描的索引的使用:
他们强制执行主键,唯一和排除约束
它们会影响统计信息收集(对于“表达式索引”)
以下是我my blog post的黄金标准查询:
SELECT s.schemaname,
s.relname AS tablename,
s.indexrelname AS indexname,
pg_relation_size(s.indexrelid) AS index_size
FROM pg_catalog.pg_stat_user_indexes s
JOIN pg_catalog.pg_index i ON s.indexrelid = i.indexrelid
WHERE s.idx_scan = 0 -- has never been scanned
AND 0 <>ALL (i.indkey) -- no index column is an expression
AND NOT EXISTS -- does not enforce a constraint
(SELECT 1 FROM pg_catalog.pg_constraint c
WHERE c.conindid = s.indexrelid)
ORDER BY pg_relation_size(s.indexrelid) DESC;
由于统计信息已重置且可以安全删除,因此尚未使用任何显示的内容。
有几点需要注意:
必须运行统计信息收集(查找“统计信息收集器”进程并查看日志中是否有关于“陈旧统计信息”的警告)
针对您的生产数据库运行查询
如果您的程序在许多站点上运行,请在所有站点上尝试(不同的用户具有不同的使用模式)
答案 1 :(得分:0)
您可以删除它们,但是应确保查询在典型工作负载之后运行。也就是说,是否有一些索引在此查询中没有显示仅在特定查询运行的某些时间使用?月末报告,每周运行等?我们碰到了几次 - 白天没有使用几个大型索引,但支持月末摘要。