为什么覆盖索引不在PostgreSQL中使用?

时间:2018-01-22 13:35:40

标签: sql indexing postgresql-9.6

我有一个简单的测试表GTable(id int, groupby int, orderby int, padding varchar(1000))。我在SQL Server 2016,PostgreSQL 9.6.1和Oracle 12c中有这个表,几乎有相同的数据。 Bellow,你可以看到用于在PostgreSQL中创建表的脚本。

PostgreSQL数据

CREATE TABLE GTable (
    id INT NOT NULL,
    groupby INT NOT NULL,
    orderby INT NOT NULL,
    padding VARCHAR(1000) NOT NULL
);

INSERT
INTO    GTable
SELECT  s, 
        s % 100, 
        s % 10000, 
        RPAD('Value ' || s || ' ' , 500, '*')
FROM    generate_series(1, 100000) s;

我创建了索引

CREATE INDEX ix_gtable_groupby_orderby ON gtable(groupby, orderby);

并运行以下查询

SELECT groupby, max(orderby) gmax
FROM gtable
GROUP BY groupby;

虽然Oracle和SQL Server使用索引来处理查询(使用顺序扫描),但PostgreSQL却没有。决不。我试图改变选择性,但没有成功。这是PostgreSQL解释(分析,缓冲)

"HashAggregate  (cost=8643.00..8643.10 rows=10 width=8) (actual time=54.906..54.907 rows=10 loops=1)"
"  Group Key: groupby"
"  Buffers: shared hit=4410 read=2733"
"  ->  Seq Scan on gtable  (cost=0.00..8143.00 rows=100000 width=8) (actual time=0.077..32.065 rows=100000 loops=1)"
"        Buffers: shared hit=4410 read=2733"
"Planning time: 0.096 ms"
"Execution time: 54.955 ms"

问题

因此,为什么PostgreSQL没有使用索引进行查询?是否有可能在不同的数据分布下使用索引?

的Oracle

如果有人想尝试,我会添加Oracle创建脚本

CREATE TABLE gtable (id NOT NULL, groupby NOT NULL, orderby NOT NULL, padding NOT NULL)
AS
SELECT  level, 
        mod(level, 100), 
        mod(level * 7 , 10000),
        CAST(RPAD('Value ' || level || ' ', 500, '*') AS VARCHAR2(500))
FROM    dual
CONNECT BY
level <= 1000000;

修改

我强迫PostgreSQL避免堆扫描,因为@a_horse_with_no_name建议(谢谢),我得到以下查询计划

"HashAggregate  (cost=17415.29..17415.39 rows=10 width=8) (actual time=59.014..59.016 rows=10 loops=1)"
"  Group Key: groupby"
"  Buffers: shared hit=14561"
"  ->  Bitmap Heap Scan on gtable  (cost=1629.29..16915.29 rows=100000 width=8) (actual time=10.396..36.956 rows=100000 loops=1)"
"        Heap Blocks: exact=14286"
"        Buffers: shared hit=14561"
"        ->  Bitmap Index Scan on ix_gtable_orderby_groupby  (cost=0.00..1604.29 rows=100000 width=0) (actual time=7.975..7.975 rows=100000 loops=1)"
"              Buffers: shared hit=275"
"Planning time: 0.127 ms"
"Execution time: 59.260 ms"

他现在使用索引,但无论如何都会访问gtable。我不明白为什么他仍然访问gtable,即使结果所需的所有数据都在索引中。 PostgreSQL是否有问题使用具有多个属性的索引?

0 个答案:

没有答案