暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Postgres索引、选择性和统计

原创 eternity 2022-07-25
994

由于我们经常将关系数据库用于非常简单的数据管理任务,因此往往忽视了关系数据库的绝对聪明。

将对象序列化为行,使用唯一键存储。

搜索唯一键,将行反序列化为对象。

关系数据库的真正功能是大量处理“关系”(也称为表),并在运行中找出过滤行并找到答案的最有效方法。
微信图片_20220722160021.jpg

PostgreSQL有一个无可否认的智能查询规划系统,可以根据系统中的数据自动调整。它对表进行采样以获得有关数据分布的统计信息,并使用这些统计信息选择应用于数据的连接和过滤器的顺序,以实现最高效的查询执行。

更令人惊讶的是,查询规划系统的模块化程度足以集成用户定义的数据类型,如PostGIS中的几何和地理类型。因此,涉及空间过滤器的复杂查询也可以在运行中正确规划。

统计数据目标

大多数情况下,这只是神奇的工作。该系统大致了解任何给定过滤器或连接条件的选择性,并可以使用该估计来选择最有效的操作顺序,以在复杂的关系表集合上执行多表和多过滤器查询。

但是当事情出了问题怎么办?

微信图片_20220722160158.png

默认情况下,PostgreSQL数据附带的默认统计目标为100。这意味着要填充列的统计信息,数据库将抽取300*默认统计目标=30000行的样本。

然后,系统将使用该数据填充“公共值列表”和列柱状图,其中包含大致默认的_statistics_target。

排列在帕累托分布中的一个大键表可能会给统计系统带来困难。可能有比“公共值列表”更容易容纳的公共键,因此连接规划得很糟糕。

微信图片_20220722160323.png

幸运的是,您可以转动一些特定于表的旋钮。

可以单独更改每个表和列上的统计信息目标,以便对更多数据进行采样,并收集更细粒度的统计信息。

ALTER TABLE people ALTER COLUMN age SET STATISTICS 200;

收集更多统计数据通常足以纠正规划行为。然而,在特殊情况下(例如当一个查询在强相关列上使用多个过滤器时),可能需要提取“扩展统计信息”以收集更多数据进行规划。

索引使(某些)事情更快

神奇的事情是,在下面通常有一些复杂的机器,使它透明地工作。

几乎每个数据库用户都知道有一种叫做“索引”的东西,向列中添加“索引”将加快对该列的搜索。

对于大多数应用来说,这条经验法则是正确的:索引使对少量项目的随机访问更快,但对表的插入和更新速度稍慢

但是,如果从表中访问大量项,会发生什么?
微信图片_20220722160451.jpg

索引是一棵树。在树中快速找到一个项目,这称为“索引扫描”。但是要找到很多项目,需要在树上一遍又一遍地运行。索引扫描树中的所有记录很慢。

高效的索引扫描查询将具有窄过滤器:

SELECT * FROM people WHERE age = 4;

相反,如果您对大多数记录感兴趣,那么从前到后读取表格可能会非常快。这称为“序列扫描”。

高效的序列扫描查询将具有广泛的过滤器:

SELECT * FROM people WHERE age BETWEEN 45 AND 95;

对于任何给定的过滤器,关系数据库将确定过滤器是作为索引扫描还是序列扫描运行最有效。但是怎么做?

选择性

过滤器的“选择性”是衡量过滤器返回的记录比例的指标。只返回1%记录的过滤器是“非常有选择性的”,反之亦然。

数字、字符串或日期的普通过滤器可能会将等式或范围定义为过滤器。地理对象上的空间过滤器将边界框定义为过滤器。过滤器只是一个真/假测试,列中的每个对象都可以进行该测试。

这里有两个空间滤波器,你认为哪一个更具选择性?
微信图片_20220722160631.png

红色的那个,对吗?就像上面关于AGE的SQL示例一样,较小的矩形必须返回较少的记录。但不一定。假设我们的数据表是这样的。
微信图片_20220722160702.png

因此,蓝色框是选择性的,应该使用索引扫描,红色框应该使用序列扫描。

但是等等,数据库如何知道哪个框是选择性的,而不运行查询并实际对数据应用过滤器?

统计数字

当运行ANALYZE命令时,数据库将为每个有索引的列收集“统计信息”。(在每个PostgreSQL集群的后台运行的“autovacuum”系统也是一个“autoanalyze”,在进行表维护的同时收集统计数据。)

对于整数、实数、文本和日期等数据类型,系统将收集表中经常出现的值的“通用值列表”,以及不同范围内值的频率直方图。

对于空间数据类型,系统构建了发生频率的空间直方图。因此,对于我们的示例数据集,类似这样的内容。
微信图片_20220722160741.png

数据库不再是可能包含数百万个空间对象的潜在无约束集合,现在只需快速汇总直方图中的几个单元格,以估计给定查询过滤器将返回多少特征。
微信图片_20220722160815.png

PostGIS中的空间统计分析器实际上要复杂一些:在填写直方图之前,它会调整每个维度的单元格宽度,以尝试在数据更密集的地方获得更高的分辨率。
微信图片_20220722160844.png

所有这些统计数据都是有代价的。增加统计目标将使ANALYZE命令运行稍慢,因为它会采集更多数据。这还将使查询的规划阶段变慢,因为需要通读更大的统计数据集,并与SQL中的过滤器和连接进行比较。然而,对于复杂的BI查询,更多的统计信息几乎总是值得的,以便为复杂查询获得更好的计划。

结论

PostgreSQL有一个不可否认的智能查询规划系统,可以根据系统中的数据自动调整。

PostGIS直接插入到这个聪明的系统中,并提供空间选择性估计,以确保良好的空间查询计划。

对于更复杂的情况,例如高度相关列的选择性估计,PostgreSQL还包括一个“扩展统计”系统来捕获这些情况。

喜欢这样的文章吗?

原文标题:Postgres Indexes, Selectivity, and Statistics
原文作者:Paul Ramsey
原文链接:https://www.crunchydata.com/blog/indexes-selectivity-and-statistics

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论