如何识别需要创建哪些索引

时间:2018-02-27 20:38:51

标签: database postgresql indexing postgresql-9.4

背景

我正在尝试查找可以使用索引编制的表。程序员抱怨某些表查询非常慢。

我在stackoverflow上找到了这个查询:

SELECT   schemaname, relname, seq_scan, seq_tup_read,
           idx_scan, seq_tup_read / seq_scan AS avg
FROM    pg_stat_user_tables
WHERE   seq_scan > 0
ORDER BY seq_tup_read DESC
LIMIT 20;

我尝试在我的数据库上运行,果然,我们的程序员抱怨的其中一个表出现了:

 schemaname |        relname         | seq_scan | seq_tup_read | idx_scan |  avg
------------+------------------------+----------+--------------+----------+-------
 public     | widgets                |      511 |     22834898 |        3 | 44686

根据我读到的内容,如果您的表具有比idx扫描更多的seq扫描,这是一个可以使用更多索引的表的一个很好的指示器。

问题

我的下一个补救问题是如何知道要编入索引的列?

我查询当前存在哪些索引:

testdb=# select * from pg_indexes where tablename='widgets';
 schemaname | tablename |   indexname   | tablespace |                            indexdef
------------+-----------+---------------+------------+----------------------------------------------------------------
 public     | widgets| widgets_pkey |            | CREATE UNIQUE INDEX widgets_pkey ON widgets USING btree (id)
(1 row)

这就是表格的一般情况:

testdb=# \d widgets
                                    Table "public.widgets"
  Column  |            Type             |                       Modifiers
----------+-----------------------------+-------------------------------------------------------
 id       | integer                     | not null default nextval('widgets_id_seq'::regclass)
 id_ts    | timestamp without time zone | default now()
 status   | character varying(32)       |
 class    | character varying(16)       |
 from     | character varying(32)       |
 to       | character varying(32)       |
 start_ts | integer                     |
 end_ts   | integer                     |
 elapsed  | integer                     |
Indexes:
    "widgets_pkey" PRIMARY KEY, btree (id)

任何建议将不胜感激。

1 个答案:

答案 0 :(得分:1)

使用pg_stat_statements找出导致顺序扫描的查询。

您必须将其添加到shared_preload_libraries并重新启动PostgreSQL。然后使用

创建pg_stat_statements视图
CREATE EXTENSION pg_stat_statements;

然后等待,直到收集到一些工作负载并查询视图。您可以使用表名(WHERE query ILIKE '%table_name%')过滤语句,并命令首先获取运行时间最长的语句。

这应该会显示导致顺序扫描的查询。