【发布时间】:2011-09-03 00:18:50
【问题描述】:
我想暂时禁用表中的一个索引,但我找不到任何文档表明它是可能的。
原因:我有一个索引,它可能会导致与它旨在加速的任何查询无关的查询问题。这是一个新的索引,自从它被引入以来,整个系统似乎变慢了。我只是希望能够可靠地消除它作为罪魁祸首,这似乎是最简单的方法,也欢迎其他解决方案建议以及更好的问题建议。
【问题讨论】:
标签: performance debugging postgresql indexing
我想暂时禁用表中的一个索引,但我找不到任何文档表明它是可能的。
原因:我有一个索引,它可能会导致与它旨在加速的任何查询无关的查询问题。这是一个新的索引,自从它被引入以来,整个系统似乎变慢了。我只是希望能够可靠地消除它作为罪魁祸首,这似乎是最简单的方法,也欢迎其他解决方案建议以及更好的问题建议。
【问题讨论】:
标签: performance debugging postgresql indexing
你可以戳系统目录来禁用索引:
update pg_index set indisvalid = false where indexrelid = 'test_pkey'::regclass
这意味着索引不会用于查询,但仍会更新。它是用于并发索引构建的标志之一。请注意,我只是做了一个快速测试,看看索引是否仍然在更新,请注意。
【讨论】:
indisready 设置为 false,则会禁用更新:postgresql.org/docs/current/static/catalog-pg-index.html
ERROR: permission denied for relation pg_index
begin;
drop index foo_ndx;
explain analyze select * from foo;
rollback;
我认为没有办法只禁用一个,尽管您可以在事务中执行此操作以使从中恢复非常简单。您还可以禁用 indexscan 以禁用所有索引。
另外,请确保您在查询时使用explain analyze。
【讨论】:
EXPLAIN ANALYZE 的建议很明确,可以开始弄清楚发生了什么。然后你可以说,“为什么INDEX 的存在导致index_scan 从X 到Y 的时间?”
ACCESS EXCLUSIVE lock on foo_ndx,这对其他并发查询有何影响?他们会使用、不使用索引,还是在此事务完成之前阻塞?
我已经创建(并审查了)一个函数,它可以在各种情况下执行此操作。你肯定需要小心它,但它确实有效。
CREATE OR REPLACE PROCEDURE global.enable_indexes(
IN schema_name TEXT
, IN table_name TEXT
, IN index_name TEXT
, IN enable_use BOOLEAN
, IN enable_updates BOOLEAN
, IN skip_essentials BOOLEAN DEFAULT TRUE
) AS
$$
DECLARE
each_record RECORD;
BEGIN
/*
USAGE:
schema_name:
- filters down by schema name
- if NULL then does not filter
table_name:
- filters down by table name (careful - not schema qualified)
- if NULL then does not filter
index_name:
- filters down by index name (careful - not schema qualified)
- if NULL then does not filter
enable_use:
- This SETs the index as being available for use.
- If enable_updates is FALSE, then automatically FALSE
enable_updates:
- This SETs the index to be updated (which doesn't imply that it is enabled for use)
- When this was previously FALSE for the given index, then when setting to true will also trigger a rebuild of the index
skip_essentials:
- When this is true, PRIMARY and UNIQUE indexes will not be included in the scope (no changes).
- Optional
*/
IF array_replace(ARRAY[schema_name, table_name, index_name], NULL, '') <@ ARRAY[''] THEN
RAISE EXCEPTION 'Error: Must specify at least one of schema_name | table_name | index_name';
END IF;
IF enable_updates IS FALSE THEN
enable_use := FALSE;
RAISE INFO 'FYI: Because enable_updates is FALSE, then likewise enable_use must be as well';
END IF;
FOR each_record IN
select
indexrelid
, (schemaname||'.'||indexname) as index_name
, indisvalid
, indisready
, (schemaname||'.'||tablename) as table_name
, (CASE WHEN indisready IS FALSE and enable_use IS TRUE AND enable_updates IS TRUE THEN TRUE ELSE FALSE END) as needs_rebuilding
FROM pg_indexes, pg_index
WHERE
indexrelid = (schemaname||'.'||indexname)::regclass
AND case when schema_name <> '' THEN schemaname = schema_name ELSE TRUE END
AND case when table_name <> '' THEN tablename = table_name ELSE TRUE END
AND case when index_name <> '' THEN indexname = index_name ELSE TRUE END
AND case when true THEN least(indisprimary, indisunique) = FALSE ELSE TRUE END
AND case when skip_essentials THEN least(indisprimary, indisunique) = FALSE ELSE TRUE END
LOOP
BEGIN
RAISE INFO 'Set index % to have use % and updates %.'
, each_record.index_name
, (case when each_record.indisvalid AND enable_use THEN 'enabled (not changed)' WHEN NOT each_record.indisvalid AND enable_use THEN 'enabled (changed)' else 'disabled' END)
, (case when each_record.indisready AND enable_updates THEN 'enabled (not changed)' WHEN NOT each_record.indisready AND enable_updates THEN 'enabled (changed)' else 'disabled' END)
;
UPDATE pg_index
SET
indisvalid = enable_use
, indisready = enable_updates
WHERE
indexrelid = each_record.indexrelid
;
IF each_record.needs_rebuilding THEN
RAISE INFO '... Reindexing and Analyzing %', each_record.index_name;
EXECUTE format('REINDEX INDEX %1$s; ANALYZE %2$s;', each_record.index_name, each_record.table_name);
END IF;
COMMIT;
END;
END LOOP;
END
$$
LANGUAGE plpgsql
;
【讨论】:
\d tags 现在没有在tags 上显示索引(这是在时间之前运行call enable_indexes('', 'tags', '', true, true, false); 然后call enable_indexes('', 'tags', '', false, false, false);。我也有f 作为pg_catalog.pg_class.relhasindex 的值@ 987654328@。我有更新了relhasindex = 't',但tags 上的索引仍未显示。现在我正在运行reindex table tags。
reindex table tags; 显然解决了这个问题。