为什么PostgreSQL没有在小表上使用我的索引?

时间:2013-03-18 10:39:44

标签: sql postgresql postgresql-performance

我在PostgreSQL中有以下表格:

CREATE TABLE index_test
(
    id int PRIMARY KEY NOT NULL,
    text varchar(2048) NOT NULL,
    last_modified timestamp NOT NULL,
    value int,
    item_type varchar(2046)
);
CREATE INDEX idx_index_type ON index_test ( item_type );
CREATE INDEX idx_index_value ON index_test ( value )

我做了以下选择:

explain select * from index_test r where r.item_type='B';
explain select r.value from index_test r where r.value=56;

执行计划的解释如下:

Seq Scan on index_test r  (cost=0.00..1.04 rows=1 width=1576)
    Filter: ((item_type)::text = 'B'::text)'

据我了解,这是一个全表扫描。问题是:为什么我的索引没有被使用?

可能是,原因是我桌子上的行太少了?我只有20个。你能不能给我一个SQL语句,用随机数据轻松填充我的表来检查索引问题?

我找到了这篇文章:http://it.toolbox.com/blogs/db2luw/how-to-easily-populate-a-table-with-random-data-7888,但它对我不起作用。声明的效率无关紧要,只有简单。

2 个答案:

答案 0 :(得分:4)

  

也许,原因是我桌上的行数太少了?

是。对于表中的总共20行,seq扫描总是比索引扫描更快。有可能这些行无论如何都位于单个数据库块中,因此seq扫描只需要一个I / O操作。

如果您使用

explain (analyze true, verbose true, buffers true) select ....

你可以看到更多关于真实情况的细节。

顺便说一句:您不应该使用text作为列名,因为它也是Postgres中的数据类型(因此也是保留字)。

答案 1 :(得分:1)

您找到的示例是针对DB2的,您可以使用generate_series来执行此操作。 例如:

INSERT INTO index_test(data,last_modified,value,item_type) 
SELECT
    md5(random()::text),now(),floor(random()*100),md5(random()::text) 
    FROM generate_series(1,1000);
SELECT max(value) from index_test;

http://sqlfiddle.com/#!12/52641/3

上面小提琴中的第二个查询应该使用仅索引扫描。