Performance 为什么我的Postgres SQL查询不使用索引
我有一张约2300万行的销售积分表。它在store_id、book_id上有一个b树索引。我希望下面的查询使用该索引,但EXPLAIN表明它正在进行顺序扫描:Performance 为什么我的Postgres SQL查询不使用索引,performance,postgresql,postgresql-9.2,heroku-postgres,Performance,Postgresql,Postgresql 9.2,Heroku Postgres,我有一张约2300万行的销售积分表。它在store_id、book_id上有一个b树索引。我希望下面的查询使用该索引,但EXPLAIN表明它正在进行顺序扫描: select distinct store_id, book_id from sales_points 以下是EXPLAIN的输出: Unique (cost=2050448.88..2086120.31 rows=861604 width=8) -> Sort (cost=2050448.88..2062339.35
select distinct store_id, book_id from sales_points
以下是EXPLAIN的输出:
Unique (cost=2050448.88..2086120.31 rows=861604 width=8)
-> Sort (cost=2050448.88..2062339.35 rows=23780957 width=8)
Sort Key: store_id, book_id
-> Seq Scan on sales_points (cost=0.00..1003261.87 rows=23780957 width=8)
如果我这样做,它会使用索引:
select distinct book_id from sales_points where store_id = 1
以下是此查询的解释输出:
HashAggregate (cost=999671.02..999672.78 rows=587 width=4)
-> Bitmap Heap Scan on sales_points (cost=55576.17..998149.04 rows=3043963 width=4)
Recheck Cond: (store_id = 1)
-> Bitmap Index Scan on index_sales_points_on_store_id_and_book_id (cost=0.00..55423.97 rows=3043963 width=0)
Index Cond: (store_id = 1)
以下是DDL表:
CREATE TABLE sales_points
(
id serial NOT NULL,
book_id integer,
store_id integer,
date date,
created_at timestamp without time zone,
updated_at timestamp without time zone,
avg_list_price numeric(5,2),
royalty_amt numeric(9,2),
currency character varying(255),
settlement_date date,
paid_sales integer,
paid_returns integer,
free_sales integer,
free_returns integer,
lent_units integer,
lending_revenue numeric(9,2),
is_placeholder boolean,
distributor_id integer,
source1_id integer,
source2_id integer,
source3_id integer,
CONSTRAINT sales_points_pkey PRIMARY KEY (id)
)
WITH (
OIDS=FALSE
);
以下是索引表达式:
CREATE INDEX index_sales_points_on_store_id_and_book_id
ON sales_points
USING btree
(store_id, book_id);
那么为什么Postgres不使用索引来加速选择呢?好吧,我认为你的索引在需要的时候可以正常工作。您的第一个查询没有WHERE子句,因此Postgres无论如何都必须检索表中的所有记录 仅用于测试,您可以通过禁用顺序扫描强制使用索引:
SET enable_seqscan = OFF;
Postgres根据varoius条件选择其扫描计划。摘自:
…当不使用索引时,强制使用索引对测试非常有用。有一些运行时参数可以关闭各种计划类型。例如,关闭顺序扫描启用_seqscan和嵌套循环联接启用_nestloop(最基本的计划)将强制系统使用不同的计划。如果系统仍然选择顺序扫描或嵌套循环联接,那么可能有一个更根本的原因导致没有使用索引
第一个查询只能通过查看索引返回,9.2确实有索引扫描。所以这个问题有点正确。@a_horse_,没有名字,我没有说这不是一个正确的问题;我指的是你的声明Postgres必须检索表中的所有记录-它也可以是索引。表的定义是什么?你能发布DDL吗?