面试经典问题,如何提高数据库的性能?

简介

一个有趣的面试问题,我已经听到并问过很多次了。

"你将如何提高数据库的性能?"

我喜欢这个问题,因为,就像我讨论过,它从更广泛的角度来衡量候选人的技能。云计算架构师会考虑数据库的架构,考虑读取复制和分片,后端或全栈工程师可能会考虑应用层面的变化,如优化的SQL查询、连接池,而数据库人员可能会考虑数据库的配置、插件等。

这个问题可能有很多答案,因为我想深入了解每个答案,所以我将分别写三篇文章,每篇都针对某一类答案。

第一篇将更多地讨论应用层面和SQL的变化。这些可能是我对直接编写代码的开发人员的期望(例如,编写与数据库服务器互动的NodeJS、Python应用程序的开发人员)。

第二种是要更注重架构层面的变化,管理服务等。他们会更关注云计算架构师或对系统设计概念有良好了解的人。

第三组答案将更注重于数据库和操作系统的配置。

请记住,这是一个非常广泛的话题,这是我对如何回答这个问题的看法,我将提供进一步阅读的链接,并尽可能多地提供实际的例子。

我也在使用软件工程的stackexchange数据集作为我的例子,你可以找到在使用Pandas将数据加载到Postgres之前,我还对数据进行了一些转换和调整,如果你有兴趣了解更多,请告诉我,我可以分享jupyter-notebook。这些数据相当容易理解,我的大多数例子应该仅限于Posts表,它简单地定义了StackOverflow上发布的问题,属性包括标题、正文、创建日期等。

问题

问题是,"我的数据库越来越慢,你会如何提高它的性能?". 在这篇文章中,我假设是一个SQL数据库,特别是Postgres。

把这个问题看成是一个两部分的问题,尽管它没有明确这样说。第一部分是 "为什么",第二部分是如何解决。为了理解 "为什么",你需要对问题进行调试,一旦你知道了数据库性能缓慢的原因,你就可以提出一个可能的解决方案。

为了便于阅读,我从可能的答案开始,涵盖与每个答案相关的权衡,然后我将解决你需要提出的反面问题,以调试问题的原因。

在你向下滚动之前,想一想你会如何回答这个问题,如果你发现我的文章中没有包括的内容,请在评论中告诉我。

可能的答案

请记住,每一个答案都是有取舍的。

索引

如果你的SELECT查询变得非常慢,因为你在检查某个条件,索引可以提供一种方法来改善你的数据库读取性能。

你可以在一组特定的列上创建一个索引,数据库将创建一个数据结构来保存数据库的这些列,这样你就可以得到这些列的快速查询。

例如,如果我想获取用户user8创建的帖子,我可以运行以下查询

SELECT * FROM posts WHERE owner_display_name=user8;

然而,这迫使数据库扫描表中的所有行,以找到owner_display_name为 "user8 "的帖子。这种类型的扫描被称为顺序扫描,因为数据库正在扫描整个表。正如名字所暗示的,这种类型的查找不是最优化的解决方案。

运行上面的查询,大约需要150ms的时间来执行。这个查询的查询计划(数据库对如何为你的查询读取表所做的规划)也表明,它将对这个查询进行顺序扫描

面试经典问题,如何提高数据库的性能?插图亿华云

要得到同样的结果,一个更好的方法是在列owner_display_name上创建一个索引。这将创建一个单独的数据结构,数据库可以使用这个新的数据结构快速查询该列的特定值。

创建一个索引很简单。

CREATE INDEX posts_owner_display_name_idx ON posts (owner_display_name)。

一旦我们创建了索引,我们就不需要做任何其他事情来使用它。数据库足够聪明,知道什么时候使用索引,什么时候不使用。运行同样的查询。

SELECT * FROM posts WHERE owner_display_name=user8;

我们现在得到了完全不同的结果。现在查询在2ms左右就完成了!这比没有索引时快了50倍。这比没有索引时快了50倍!

查询计划还指出,数据库现在正在使用我们所创建的索引

面试经典问题,如何提高数据库的性能?插图1亿华云

虽然没有什么是免费的,索引也有一定的成本。

由于我们现在正在创建一个不同的数据结构来存储你表中的相同数据,所以你的表的每一行都需要更多的存储空间。除此之外,现在数据库必须确保每当你向表中添加新的行时,索引都是最新的,所以在编写新的行时,它也为数据库增加了更多的工作。

索引可以是修复数据库读取性能的一个好方法,但可能会减慢写入性能。

索引本身就是一个复杂的话题,网上有很多资源可以更深入地讨论其性能影响。 如果你想更多地了解与索引相关的权衡,那么 "索引 "是一个很好的起点。 如果你想了解更多关于索引的信息,视频也更详细地解释了索引。

创建物化视图

你可以在数据库中创建两种类型的视图,简单视图和物化视图。

简单视图作为查询的别名,而物化视图则存储查询的结果。这意味着,你可以预先计算查询,将结果存储在物化视图中,并在用户实际要求时快速向用户显示结果,而不是在用户请求时运行查询。

让我们用一个例子来讨论这个问题。假设我想根据帖子的浏览量来了解帖子的类别 --

面试经典问题,如何提高数据库的性能?插图2亿华云

做到这一点的一个方法是运行以下查询

SELECT

CASE

WHEN view_count

THE END
Copyright © 2024 亿华云