为什么PostgreSQL对索引列执行顺序扫描?

时间:2011-03-05 12:17:20

标签: postgresql indexing sequence database-scan

非常简单的例子 - 一个表,一个索引,一个查询:

CREATE TABLE book
(
  id bigserial NOT NULL,
  "year" integer,
  -- other columns...
);

CREATE INDEX book_year_idx ON book (year)

EXPLAIN
 SELECT *
   FROM book b
  WHERE b.year > 2009

给了我:

Seq Scan on book b  (cost=0.00..25663.80 rows=105425 width=622)
  Filter: (year > 2009)

为什么它不执行索引扫描? 我错过了什么?

4 个答案:

答案 0 :(得分:184)

如果SELECT返回表中所有行的大约5-10%,则顺序扫描比索引扫描快得多。

这是因为索引扫描需要每行几个 IO操作(查找索引中的行,然后从堆中检索行)。顺序扫描每行只需要一个IO - 或者甚至更少,因为磁盘上的块(页面)包含多行,因此可以通过单个IO操作获取多个行。

Btw:对于其他DBMS也是如此 - 一些优化作为“仅索引扫描”而被忽略(但对于SELECT *,这样的DBMS极不可能用于“仅索引扫描”)

答案 1 :(得分:12)

你有ANALYZE表/数据库吗?那statistics怎么样?当有许多记录,其中年份> 2009年,顺序扫描可能比索引扫描更快。

答案 2 :(得分:1)

@a_horse_with_no_name解释得很好。另外,如果您确实要使用索引扫描,则通常应在where子句中使用有界范围。例如- > 2019年和<2020年。

很多时候,表上的统计信息没有更新,由于限制,可能无法更新。在这种情况下,优化器将不会知道> 2019年应该进行多少行。因此,它将选择顺序扫描来代替全部知识。有界的分区通常会解决问题。

答案 3 :(得分:0)

在索引扫描中,读取头从一行跳到另一行,这比读取下一个物理块要慢1000倍(在顺序扫描中)。

因此,如果(要检索的记录数* 1000)少于记录总数,则索引扫描将表现更好。