postgresql - Postgres 查询优化(强制索引扫描)

标签 postgresql indexing query-optimization postgresql-9.1 postgresql-performance

下面是我的查询。我试图让它使用索引扫描,但它只会进行序列扫描。

顺便说一句,metric_data 表有 1.3 亿行。 metrics 表有大约 2000 行。

metric_data 表列:

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

如何让这个查询使用我的 PRIMARY KEY 索引?

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[]))

最佳答案

出于测试目的,您可以通过“禁用”顺序扫描来强制使用索引 - 最好仅在当前 session 中使用:

SET enable_seqscan = OFF;

不要不要在生产服务器上使用它。 Details in the manual here.

我引用了“禁用”,因为您实际上无法禁用顺序表扫描。但是现在任何其他可用的选项都更适合 Postgres。这将证明 (metric_id, t) 上的多列索引可以使用 - 只是不如前导列上的索引有效。

通过切换 PRIMARY KEY 中的列顺序,您可能会获得更好的结果(以及用于在幕后实现它的索引)到 (t, metric_id) .或者创建一个额外的索引,其中包含类似这样的反向列。

您通常不必通过手动干预强制执行更好的查询计划。如果设置 enable_seqscan = OFF导致一个好得多的计划,但您的数据库中可能有些地方不对。考虑这个相关的答案:

关于postgresql - Postgres 查询优化(强制索引扫描),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14554302/

相关文章:

使用格式化日期函数时 SQL 查询运行速度非常慢

json - PostgreSQL 9.5 - 将 NULL 与 JSON 合并时更新不起作用

linux - 如何释放 psql 端口?

sql - 当事件范围超过一个月时按月汇总事件成本(在 rails 3 中)

sql-server - SQL Server 中的索引

javascript - 从所选元素中获取索引

azure - 将 PDF 中的表格提取到 Azure 搜索

mysql - 如何正确地将索引应用到我的 mysql 数据库

ruby-on-rails - 为什么 Foo.first 返回最后一条记录?

mysql - 查询成本是 MySQL 查询优化的最佳指标吗?