首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >PostgreSQL 性能优化创建正确的索引具有不确定性

PostgreSQL 性能优化创建正确的索引具有不确定性

作者头像
AustinDatabases
发布于 2022-05-19 00:54:24
发布于 2022-05-19 00:54:24
1.1K00
代码可运行
举报
文章被收录于专栏:AustinDatabasesAustinDatabases
运行总次数:0
代码可运行

索引在数据库的查询中起到的作用毋庸置疑,但时常有人提出索引的建立的问题,to be or not to be 的问题。

问题1 索引建立后,就不再变动了 ?

大多数的问题是在于索引建立后并不能一直良好的工作,主要有以下几个问题

1 重复功能的索引,让查询无法把握或者在管理人员不知情的情况下,走了其他的索引,索引并不能有效的工作,并成为负担。

2 索引在PG的数据改变变化导致索引失效的问题。

3 随着应用场景的变化,索引已经不能完成原先设计的功能,而成为查询中导致性能低下的一个瓶颈。

4 索引建立的过多,导致数据的写入性能产生问题。

索引的建立和不建立的问题

在有效评估数据表的大小的情况下,一个索引建立不建立是一个问题,如果数据量小,则一般可以不建立索引,但是问题是

1 怎样的数量算小

2 未来数据增加怎么办

所以建立索引是一个非常需要经验和考量的问题,而并不是建立他就完事了,针对索引整体的跟踪体系,以及分析体系,才是一个让你的数据库更好工作的起点。

select indexrelid,schemaname,relname,indexrelname,idx_scan,idx_tup_read from pg_stat_all_indexes where schemaname not in ('pg_toast','pg_catalog');

通过这个表可以查看到底有多少索引并不在工作中,或者从PG的开机后,并没有进行工作。但是这样的工作对于主键是不合适的,所以查看这样的工作可以对主键进行一个屏蔽。

同时不可以忽略的问题是随着数据的增长,索引无法完全加载到内存当中,导致的数据查询性能的问题。

同时在数据查询的过程中,索引的也会经历一个曲线,有索引和无索引的表象。

除此以外即使有了索引的情况下,还会产生数据查询条件于数据的采样分布的问题。

我们用下面的例子来说明,同样的表,同样的查询的方式

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
postgres=# explain SELECT
postgres-# p.last_name,
postgres-# p.first_name
postgres-# FROM passenger p
postgres-# JOIN boarding_pass bp USING (passenger_id)
postgres-# JOIN booking_Leg bl USING (booking_leg_id)
postgres-# JOIN flight USING(flight_id)
postgres-# WHERE departure_airport='LAX'
postgres-# AND lower(last_name)='clark';
                                                        QUERY PLAN                                                        
--------------------------------------------------------------------------------------------------------------------------
 Gather  (cost=243530.39..638952.23 rows=2091 width=12)
   Workers Planned: 4
   ->  Parallel Hash Join  (cost=242530.39..637743.13 rows=523 width=12)
         Hash Cond: (bl.flight_id = flight.flight_id)
         ->  Nested Loop  (cost=233079.69..628209.42 rows=31617 width=16)
               ->  Parallel Hash Join  (cost=233079.25..573669.83 rows=31617 width=20)
                     Hash Cond: (bp.passenger_id = p.passenger_id)
                     ->  Parallel Seq Scan on boarding_pass bp  (cost=0.00..323991.73 rows=6323373 width=16)
                     ->  Parallel Hash  (cost=232824.35..232824.35 rows=20392 width=16)
                           ->  Parallel Seq Scan on passenger p  (cost=0.00..232824.35 rows=20392 width=16)
                                 Filter: (lower(last_name) = 'clark'::text)
               ->  Index Scan using booking_leg_pkey on booking_leg bl  (cost=0.44..1.73 rows=1 width=8)
                     Index Cond: (booking_leg_id = bp.booking_leg_id)
         ->  Parallel Hash  (cost=9391.88..9391.88 rows=4706 width=4)
               ->  Parallel Bitmap Heap Scan on flight  (cost=307.96..9391.88 rows=4706 width=4)
                     Recheck Cond: (departure_airport = 'LAX'::bpchar)
                     ->  Bitmap Index Scan on idx_flight_airport_status_update_ts  (cost=0.00..305.14 rows=11295 width=0)
                           Index Cond: (departure_airport = 'LAX'::bpchar)
(18 rows)

整体的过程

1 并行扫描passenger 表,过滤 last_name 条件

2 并行扫描 boarding_pass 表

3 index scan booking_Leg 表

4 2个表进行hash join passenger 和 boarding_pass

5 将2个表的结果与booking_Leg 表的信息进行nested loop join

6 针对flight 表进行进行bitmap 索引扫描符合 departure_airport 等于 LAX的数据

7 针对三个表和 flight 表的结果进行 hash join

8 最终产生结果

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
postgres=# 
postgres=# explain SELECT
postgres-# p.last_name,
postgres-# p.first_name
postgres-# FROM passenger p
postgres-# JOIN boarding_pass bp USING (passenger_id)
postgres-# JOIN booking_Leg bl USING (booking_leg_id)
postgres-# JOIN flight USING(flight_id)
postgres-# WHERE departure_airport='LAX'
postgres-# AND lower(last_name)=' smith';
                                                        QUERY PLAN                                                        
--------------------------------------------------------------------------------------------------------------------------
 Gather  (cost=243530.39..638952.23 rows=2091 width=12)
   Workers Planned: 4
   ->  Parallel Hash Join  (cost=242530.39..637743.13 rows=523 width=12)
         Hash Cond: (bl.flight_id = flight.flight_id)
         ->  Nested Loop  (cost=233079.69..628209.42 rows=31617 width=16)
               ->  Parallel Hash Join  (cost=233079.25..573669.83 rows=31617 width=20)
                     Hash Cond: (bp.passenger_id = p.passenger_id)
                     ->  Parallel Seq Scan on boarding_pass bp  (cost=0.00..323991.73 rows=6323373 width=16)
                     ->  Parallel Hash  (cost=232824.35..232824.35 rows=20392 width=16)
                           ->  Parallel Seq Scan on passenger p  (cost=0.00..232824.35 rows=20392 width=16)
                                 Filter: (lower(last_name) = ' smith'::text)
               ->  Index Scan using booking_leg_pkey on booking_leg bl  (cost=0.44..1.73 rows=1 width=8)
                     Index Cond: (booking_leg_id = bp.booking_leg_id)
         ->  Parallel Hash  (cost=9391.88..9391.88 rows=4706 width=4)
               ->  Parallel Bitmap Heap Scan on flight  (cost=307.96..9391.88 rows=4706 width=4)
                     Recheck Cond: (departure_airport = 'LAX'::bpchar)
                     ->  Bitmap Index Scan on idx_flight_airport_status_update_ts  (cost=0.00..305.14 rows=11295 width=0)
                           Index Cond: (departure_airport = 'LAX'::bpchar)
(18 rows)

在我们查询条件变化的情况下,我们的查询执行计划基本是相同的

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
postgres=# 
postgres=# explain SELECT
postgres-# p.last_name,
postgres-# p.first_name
postgres-# FROM passenger p
postgres-# JOIN boarding_pass bp USING (passenger_id)
postgres-# JOIN booking_Leg bl USING (booking_leg_id)
postgres-# JOIN flight USING(flight_id)
postgres-# WHERE departure_airport='FUK' AND lower(last_name)='smith';
                                                        QUERY PLAN                                                        
--------------------------------------------------------------------------------------------------------------------------
 Gather  (cost=1001.31..124225.90 rows=69 width=12)
   Workers Planned: 2
   ->  Nested Loop  (cost=1.31..123219.00 rows=29 width=12)
         ->  Nested Loop  (cost=0.88..113476.86 rows=5785 width=8)
               ->  Nested Loop  (cost=0.44..58845.93 rows=4092 width=4)
                     ->  Parallel Seq Scan on flight  (cost=0.00..12125.21 rows=156 width=4)
                           Filter: (departure_airport = 'FUK'::bpchar)
                     ->  Index Scan using booking_leg_flight_id on booking_leg bl  (cost=0.44..298.67 rows=82 width=8)
                           Index Cond: (flight_id = flight.flight_id)
               ->  Index Scan using boarding_pass_booking_leg_id on boarding_pass bp  (cost=0.44..13.13 rows=22 width=16)
                     Index Cond: (booking_leg_id = bl.booking_leg_id)
         ->  Index Scan using passenger_pkey on passenger p  (cost=0.43..1.68 rows=1 width=16)
               Index Cond: (passenger_id = bp.passenger_id)
               Filter: (lower(last_name) = 'smith'::text)
(14 rows)

而当我们还采用同样的查询方式,但将departure_airport 的条件变化后,那么查询计划整体改变了

1 对flight 表进行并行扫描

2 对booking_leg 表进行进行索引的扫描

3 针对这两个数据的集合进行nested loop 的操作

4 在对boarding_pass 表进行索引的扫描

5 在针对两个表的结果集和boarding_pass的结果集进行nested_loop查询

6 在针对passenger 表进行索引的扫描

7 最后在进行3个表的结果与passenger 的表的进行nested loop 的操作

这三个例子中,可以发现随着 departure_airport的表换,整体的查询方式和执行计划也进行了改变。

所以虽然索引都一样,但查询条件的变化也会引起查询的速度和时间的变化

具体的问题在于一个departure_airport 的数据量仅仅有 468 另一个的数据量在 11804.

总结,索引是解决查询速度和优化查询的一个方法,但是查询条件本身的变化也针对整体的数据查询效率也具有一个决定性的条件。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-04-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AustinDatabases 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
软件测试:黑白盒测试的区别及白盒测试全面解析与应用
白盒测试方法应用于代码评审、单元程序之中,而黑盒测试方法则应用于模块、组件等大单元的功能测试之中。
Srlua
2024/10/19
4450
软件测试:黑白盒测试的区别及白盒测试全面解析与应用
白盒测试:如何进行代码级别的测试?
白盒测试也称结构测试,透明盒测试。主要用于单元测试阶段,代码和逻辑的测试,重点复杂的测试,是一种测试用例设计方法,不同于黑盒测试,白盒测试是可以看到内部代码如何运作的,可通过测试来检测产品内部是否符合规定正常运行。
测试开发技术
2023/08/21
4280
白盒测试:如何进行代码级别的测试?
软件工程黑盒白盒测试
等价类划分法是把程序的 输入域 划分为若干部分,然后从每个部分中选取少数代表性数据当作测试用例。
wsuo
2021/01/14
1.6K0
软件工程黑盒白盒测试
白盒测试用例设计方法有哪些_软件测试语句覆盖测试用例
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
全栈程序员站长
2022/11/04
5720
白盒测试用例设计方法有哪些_软件测试语句覆盖测试用例
白盒测试中的几种覆盖方法
文章转自:http://www.51testing.com/html/44/n-3713444.html 白盒测试用例设计的一个很重要的评估标准就是对代码的覆盖度。一说到覆盖,大家都感觉非常熟悉,但是常见的覆盖都有哪些?各自有什么优缺点?在白盒测试的用例设计中我们应该如何自如地运用呢?今天小编就为大家总结了一下几种常见的覆盖以及各自的优缺点。 白盒测试中常见的覆盖有六种:语句覆盖、判定覆盖、条件覆盖、判定/条件覆盖、组合覆盖和路径覆盖。下面我们就分别看看这几种不同的覆盖究竟是什么鬼。 一、语句覆盖(St
张俊怡
2018/04/24
10.1K0
白盒测试中的几种覆盖方法
白盒测试技术_静态白盒测试
它是度量测试完整性的一个工具,通常可以分为逻辑覆盖和功能覆盖。覆盖率 =(被执行到的项数/总项数)* 100%
全栈程序员站长
2022/09/27
1.6K0
白盒测试技术_静态白盒测试
软件测试基础知识 – 说一说黑盒与白盒的测试方法[通俗易懂]
分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请点击http://www.captainbed.net
全栈程序员站长
2022/09/05
1.1K0
技术分享 | 白盒测试方法论
白盒测试又称为结构测试、透明盒测试、逻辑驱动测试或基于代码的测试。白盒测试是一种测试用例设计方法。盒子指的是被测试的软件,白盒指的是盒子是可视的,即清楚盒子内部的东西以及里面是如何运作的。"白盒"法全面了解程序内部逻辑结构,对所有逻辑路径进行测试。"白盒"法是穷举路径测试。在使用这一方案时,测试者必须检查程序的内部结构,从检查程序的逻辑着手,得出测试数据。
霍格沃兹测试开发
2022/03/22
5170
软考高级:白盒测试用例(语句覆盖、判断覆盖、条件组合覆盖、条件判定组合覆盖)概念和例题
白盒测试是一种软件测试方法,它检查程序内部的逻辑结构。在白盒测试中,测试用例是基于程序的内部代码和逻辑来设计的。下面是几种常见的白盒测试用例设计方法的概念解释以及它们对应的Java代码示例。
明明如月学长
2024/05/24
1.2K0
白盒测试的测试用例设计方法
对简单的程序流程而言,确定程序的路径有多少条可通过:语句覆盖(覆盖率100%);分支(判定)覆盖(覆盖率85%);条件覆盖;分支-条件覆盖;条件组合覆盖;路径覆盖(覆盖率80%)来确定,这也是白盒测试的主要技术。
全栈程序员站长
2022/11/07
1.4K0
白盒测试的测试用例设计方法
图解-白盒测试之逻辑覆盖
白盒测试是一种测试用例设计方法,盒子指的是被测试的软件,白盒指的是盒子是可视的,即清楚盒子内部的东西以及里面是如何运作的。"白盒"法全面了解程序内部逻辑结构、对所有逻辑路径进行测试。"白盒"法是穷举路径测试。在使用这一方案时,测试者必须检查程序的内部结构,从检查程序的逻辑着手,得出测试数据。
wangmcn
2022/07/26
1.1K0
图解-白盒测试之逻辑覆盖
测试技术|白盒测试以及代码覆盖率实践
白盒测试也称逻辑驱动测试,是针对被测单元内部是如何进行工作的测试。它根据程序的控制结构设计测试用例,主要用于软件程序验证,属于基于代码的测试技术。与之相对应的黑盒测试是从用户角度对软件进行测试。
互联网金融打杂
2022/08/01
2.1K0
测试技术|白盒测试以及代码覆盖率实践
黑盒测试和白盒测试的区别
1.        软件测试方法:白盒测试、黑盒测试、灰盒测试、静态测试、动态测试
庞小明
2018/10/11
9.8K1
白盒测试?看这一篇就够了
点击上方蓝字“一个正经的测试“关注我,每周早上08:30准时推送,每月不定期赠送技术书籍。
一个正经的AI
2024/01/22
8850
白盒测试?看这一篇就够了
【白盒测试】单元测试的理论基础及用例设计技术(6种)详解
综上,白盒测试和黑盒测试的主要区别在于测试者对系统内部结构的了解程度。白盒测试关注程序内部逻辑和代码覆盖率,而黑盒测试则关注系统的功能和用户体验。
SarPro
2024/04/25
9530
【白盒测试】单元测试的理论基础及用例设计技术(6种)详解
浅谈黑盒测试和白盒测试
  从图中可以直接看出来,黑盒测试就当整个程序是个黑盒子,我们看不到它里面做了些什么事情,只能通过输入输出看是否能得到我们所需的来测试。而白盒测试可以当盒子是透明的,里面的一切我们都看的清楚,从而我们可以通过去测内部结构来测试。
lyb-geek
2018/07/26
4.1K0
浅谈黑盒测试和白盒测试
白盒测试方法与黑盒测试方法简析
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
全栈程序员站长
2022/11/10
1.5K0
软件测试技术之: 白盒测试和黑盒测试[通俗易懂]
一般地,我们将软件测试活动分为以下几类:黑盒测试、白盒测试、静态测试、动态测试、手动测试、自动测试等等。
全栈程序员站长
2022/10/02
7.1K0
软件测试技术之: 白盒测试和黑盒测试[通俗易懂]
白盒测试 | 用例设计方法之条件组合覆盖
条件组合覆盖:列出所有判定条件中可能的取值组合,使得每个判定条件结果的所有可能组合至少出现一次
王大力测试进阶之路
2022/03/14
2.3K0
白盒测试 | 用例设计方法之条件组合覆盖
测试开发需要学习的知识结构[通俗易懂]
黑盒测试也称功能测试或数据驱动测试,它是在已知产品所应具有的功能,通过测试来检测每个功能是否都能正常使用,在测试时,把程序看作一个不能打开的黑盆子,在完全不考虑程序内部结构和内部特性的情况下,测试者在程序接口进行测试,它只检查程序功能是否按照需求规格说明书的规定正常使用,程序是否能适当地接收输入数锯而产生正确的输出信息,并且保持外部信息(如数据库或文件)的完整性。黑盒测试方法主要有等价类划分、边值分析、因—果图、错误推测等,主要用于软件确认测试。 “黑盒”法着眼于程序外部结构、不考虑内部逻辑结构、针对软件界面和软件功能进行测试。“黑盒”法是穷举输入测试,只有把所有可能的输入都作为测试情况使用,才能以这种方法查出程序中所有的错误。实际上测试情况有无穷多个,人们不仅要测试所有合法的输入,而且还要对那些不合法但是可能的输入进行测试。
全栈程序员站长
2022/07/28
5590
测试开发需要学习的知识结构[通俗易懂]
推荐阅读
相关推荐
软件测试:黑白盒测试的区别及白盒测试全面解析与应用
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验