下面是我的问题.我试图让它使用索引扫描,但它只会seq扫描.

顺便说一下,metric_data表有1.3亿行.metrics表大约有2000行.

metric_data个表列:

  metric_id integer
, t timestamp
, d double precision
, PRIMARY KEY (metric_id, t)

如何让这个查询使用主键索引?

SELECT
    S.metric,
    D.t,
    D.d
FROM metric_data D
INNER JOIN metrics S
    ON S.id = D.metric_id
WHERE S.NAME = ANY (ARRAY ['cpu', 'mem'])
  AND D.t BETWEEN '2012-02-05 00:00:00'::TIMESTAMP
              AND '2012-05-05 00:00:00'::TIMESTAMP;

说明:

Hash Join  (cost=271.30..3866384.25 rows=294973 width=25)
  Hash Cond: (d.metric_id = s.id)
  ->  Seq Scan on metric_data d  (cost=0.00..3753150.28 rows=29336784 width=20)
        Filter: ((t >= '2012-02-05 00:00:00'::timestamp without time zone)
             AND (t <= '2012-05-05 00:00:00'::timestamp without time zone))
  ->  Hash  (cost=270.44..270.44 rows=68 width=13)
        ->  Seq Scan on metrics s  (cost=0.00..270.44 rows=68 width=13)
              Filter: ((sym)::text = ANY ('{cpu,mem}'::text[]))

推荐答案

出于testing种目的,您可以通过"禁用"顺序扫描来强制使用索引——最好只在当前会话中使用:

SET enable_seqscan = OFF;

请在高效服务器上使用此选项.Details in the manual here.

我引用了"禁用",因为实际上无法禁用连续表扫描.但现在,对于博士后来说,任何其他可用的 Select 都更可取.这将证明可以使用(metric_id, t) can上的多列索引——只是不如前导列上的索引有效.

如果将PRIMARY KEY中的列顺序(以及用于实现它的索引)切换到(t, metric_id),可能会获得更好的结果.或者创建一个包含反转列的additional索引.

您通常不必通过手动干预强制执行更好的查询计划.如果设置enable_seqscan = OFF可以得到更好的much计划,那么数据库中可能存在一些不正确的地方.考虑这个相关的答案:

Postgresql相关问答推荐

Trunc函数不删除小数

Postgres 11没有强制执行外键约束?

Postgres 生成的列不是不可变的

如何在 postgres 中查询键设置为空值的 jsonb 字段

是否可以在 postgres jsonb 列中的列表上创建索引

如何在 PostgreSQL 的回归测试中测试 TYPE 发送和接收函数

函数将多列作为单列而不是多列返回

PostgreSQL 在 mySQL 中的 date_trunc

!= 和 <> 运算符有什么区别?

PostgreSQL ,从 2 个表中 Select ,但仅从表 2 中 Select 最新的元素

在 PostgreSQL 中Explain与explain analyze

在远程机器上Restore dump

将 SELECT 结果作为参数传递给 postgreSQL 函数

PostgreSQL CASE 在函数中的使用

Rails 4 迁移: has_and_belongs_to_many table name

使用 RPostgreSQL 写入特定模式

Postgis / Geodjango:无法确定数据库的 PostGIS 版本

在 Windows 7 上更改/重置 postgresql 用户密码

使用 Homebrew 安装 icu4c 版本 63

没有函数匹配给定的名称和参数类型