美文网首页
利用 PostgreSQL 部分索引提高查询语句的性能

利用 PostgreSQL 部分索引提高查询语句的性能

作者: Java入门到入坟 | 来源:发表于2020-11-16 14:52 被阅读0次

推荐阅读:

在 PostgreSQL 数据库中,部分索引(partial index)是指对表中满足特定条件的数据行进行索引。由于它不需要对全部数据进行索引,因此索引会更小,在特定场景下通过部分索引查找数据时性能会更好。本文就给大家介绍一下 PostgreSQL 中的部分索引功能。

PostgreSQL 在创建索引时可以通过一个 WHERE 子句指定需要索引的数据行,从而创建一个部分索引。例如,对于以下订单表 orders:

CREATE TABLE orders (
  id INT PRIMARY KEY,
  customer_id INT,
  status TEXT
);

INSERT INTO orders (id, customer_id, status)
SELECT
  i,
  (random()*10000)::INT,
  CASE (random() * 100)::int
    WHEN 0 THEN 'pending'
    WHEN 1 THEN 'shipped'
    ELSE 'completed'
  END
    FROM generate_series(1, 1000000) i;

该表中总共有 1000000 个订单,通常绝大部的订单都处于完成状态。一般情况下,我们只需要针对某个用户未完成的订单进行查询跟踪,因此可以创建一个基于用户编号和状态的部分索引:

CREATE INDEX full_idx ON orders (customer_id, status);

然后使用 EXPLAIN ANALYZE 命令查看 SELECT 语句的执行计划:

EXPLAIN ANALYZE
SELECT * 
FROM orders
WHERE customer_id = 5678
AND status != 'completed';

QUERY PLAN                                                                                                           |
---------------------------------------------------------------------------------------------------------------------|
Bitmap Heap Scan on orders  (cost=5.18..369.08 rows=1 width=17) (actual time=33.661..34.040 rows=1 loops=1)          |
  Recheck Cond: (customer_id = 5678)                                                                                 |
  Filter: (status <> 'completed'::text)                                                                              |
  Rows Removed by Filter: 109                                                                                        |
  Heap Blocks: exact=109                                                                                             |
  ->  Bitmap Index Scan on full_idx  (cost=0.00..5.17 rows=100 width=0) (actual time=33.526..33.526 rows=110 loops=1)|
        Index Cond: (customer_id = 5678)                                                                             |
Planning Time: 1.252 ms                                                                                              |
Execution Time: 34.180 ms                                                                                            |

输出结果显示利用索引 full_idx 扫描了 110 行,然后通过 status 过滤掉了 109 行,而不是直接通过索引扫描出所需的数据。

此时,我们可以查看一下索引 full_idx 占用的空间大小:

select pg_size_pretty(pg_table_size('full_idx'));

pg_size_pretty|
--------------|
30 MB         |

接下来我们再创建一个部分索引,只包含未完成的订单数据,从而减少索引的数据量:

CREATE INDEX partial_idx ON orders (customer_id)
WHERE status != 'completed';

索引 partial_idx 中只有 customer_id 字段,不需要 status 字段。然后再次执行相同的 EXPLAIN ANALYZE 语句,查看执行计划:

EXPLAIN ANALYZE
SELECT * 
FROM orders
WHERE customer_id = 5678
AND status != 'completed';

QUERY PLAN                                                                                                         |
-------------------------------------------------------------------------------------------------------------------|
Index Scan using partial_idx on orders  (cost=0.29..8.30 rows=1 width=17) (actual time=0.246..0.249 rows=1 loops=1)|
  Index Cond: (customer_id = 5678)                                                                                 |
Planning Time: 0.397 ms                                                                                            |
Execution Time: 0.295 ms                                                                                           |

输出结果显示 PostgreSQL 执行计划选择了索引 partial_idx,而不是 full_idx;因为这样性能更好,只需要扫描 1 行记录就可以得到结果。

同样可以查看一下索引 partial_idx 占用的空间大小:

select pg_size_pretty(pg_table_size('partial_idx'));

pg_size_pretty|
--------------|
352 kB        |

索引只有 352 KB,而不是 30 MB,因为绝大多数订单都处于完成状态。

另外,部分索引还可以用于实现其他的功能。例如,我们可以将索引 partial_idx 定义为唯一索引,从而实现每个用户只能存在一个未完成订单的约束。

DROP INDEX partial_idx;
TRUNCATE TABLE orders;

CREATE UNIQUE INDEX partial_idx ON orders (customer_id)
WHERE status != 'completed';

INSERT INTO orders(id, customer_id, status) VALUES (1, 1, 'pending');

INSERT INTO orders(id, customer_id, status) VALUES (2, 1, 'pending');
SQL 错误 [23505]: 错误: 重复键违反唯一约束"partial_idx"
  详细:键值"(customer_id)=(1)" 已经存在

用户必须完成一个订单之后才能继续生成新的订单。

相关文章

  • 利用 PostgreSQL 部分索引提高查询语句的性能

    推荐阅读: 我总结了72份面试题,累计3170页,斩获了30+互联网公司offer(含BATJM)[https:/...

  • 数据库索引

    数据库索引 索引就是为了提高查询性能而存在的, 如果在查询中索引没有提高性能, 只能说是用错了索引,或者讲是场合不...

  • 性能优化-索引

    概述 索引优化是对查询性能优化最有效的手段,索引能轻易将查询性能提高几个数量级。 索引类型 在Mysql中,索引是...

  • Mysql索引杂谈

    结论:索引是把双刃剑,可以提高数据库性能,也会影响数据库性能 利: 索引加快数据查询速度,提高数据库查询性能。 弊...

  • mysql性能优化-慢查询分析、优化索引和配置

    mysql性能优化-慢查询分析、优化索引和配置 分类:Mysql/postgreSQL 目录 一、优化概述 二、查...

  • 索引

    索引是什么 用来提高查询速度 ,但是影响更新速度。 建立索引的列是经常用到(查询) 建立索引的语句]

  • Elasticsearch SQL入门教程 --- 2022-0

    除了使用RESTful API查询Elasticsearch索引数据,也可以使用SQL语句查询索引数据,相信大部分...

  • MySQL性能调优

    MYSQL查询语句优化 mysql的性能优化包罗甚广: 索引优化,查询优化,查询缓存,服务器设置优化,操作系统和硬...

  • MySQL高级知识-查询与索引优化分析

    性能下降SQL慢、执行时间长、等待时间长 查询语句写的烂 索引失效单值索引复合索引 关联查询太多join(设计缺陷...

  • 索引概述

    索引是数据库查询提高性能的最常用的工具。可以把索引类比成书的目录。索引类型:hash索引和btree索引。MyIS...

网友评论

      本文标题:利用 PostgreSQL 部分索引提高查询语句的性能

      本文链接:https://www.haomeiwen.com/subject/tihgbktx.html