当前位置: 首页 > news >正文

顶级大厂Quora如何优化数据库性能?

Quora 的流量涉及大量阅读而非写入,一直致力于优化读和数据量而非写。

0 数据库负载的主要部分

  • 读取
  • 数据量
  • 写入

1 优化读取

1.1 不同类型的读需要不同优化

① 复杂查询,如连接、聚合等

在查询计数已成为问题的情况下,它们在另一个表中构建了计数,以便它们可以直接读取计数值而非计算计数。

② 大型扫描

他们使用 LIMIT 改变它或使用分页

③ 模式与查询之间不匹配

若:

  • 无很好的索引
  • 或索引没有足够的列
  • 或索引中的列顺序对查询来说不是最佳

则查询可能很慢,可能对数据库造成很大负载。

这种情况下,通常会修改索引以对查询进行优化。 有时查询也可修改以对索引进行优化。如:

  • 删除 select 子句中不必要的列(特别是索引中不存在的列)
  • 删除 order by 子句,改为在客户端上排序(MySQL CPU 一般比客户端 CPU 更宝贵)
  • 若该查询提供的功能不再重要,可完全删除查询

1.2 高 QPS 查询

即使使用了优化的 SQL 和良好的模式,高 QPS查询也给数据库带来很大负载。有时可能表示缓存效率低下(甚至没缓存)。

① 低效的缓存是否导致了高 QPS 查询?

缓存通常用于减少数据库 QPS。缓存键的选择可以极大地影响缓存的效率:

  • 若缓存键过于具体或狭窄,可能导致数据库出现高 QPS
  • 若缓存键太宽泛,每次查询都会从数据库中拉取大量数据
② 对用户语言表的查询

我们有一个表跟踪用户使用的语言信息。通常会查询数据库以查看用户 U 是否使用语言 L。使用(uid,language_id)作为缓存键看起来合理。如缓存未命中,将为该 uid 和 language_id 查询数据库表。

因此,将缓存键更改为仅使用 uid 确实有意义,缓存值将是有关用户使用的所有语言的信息。

以上述方式更改缓存键,会增加从库表中每次查询获取的数据量,但它将 QPS 减少超过 90%。大多数用户只使用一或几种语言。 因此,大多数情况,新的查询并没有拉取比以前更多的数据,这是一个显然的优化!

③ 查询 A2A(ask to answer)表

这里我们处理 3 个实体间的关系,即用户(谁提问或关注问题)、问题和回答者,这比 2 个实体之间的关系更不常见。

通常产品逻辑是查询:

  • 用户已请求过的所有回答者,使用缓存键 (question_id, user_id)
  • 请求过相同回答者回答一个问题的所有用户,使用缓存键 (question_id, answerer_id)

综上,A2A 表的 QPS 非常高,这意味着上述缓存效果并不明显。上述两个缓存都在使用 2 个实体作为缓存键question_id 和 user_id(可以是提问者或回答者)。

潜在缓存键数量巨大,因为它是问题数和用户数的乘积,其中只有很少的组合实际上在表中有数据。所以它可看作一个稀疏的数据集,有2维。

大多数问题的 A2A 请求数量相对较少,但有少数问题的 A2A 数量要多得多。因此,添加额外缓存,该缓存包含问题的 A2A,最多限制为 N 个,以便我们捕获大多数问题。 该缓存的键只是 question_id。 如缓存列表大小小于N,我们知道缓存是完整的。 否则,缓存不完整,我们不会使用缓存。

这额外缓存帮助显著减少 A2A 表上的 QPS(在 50% 到 66% 的范围内)。 还对产品逻辑进行了其他更改,以提高效率,但 QPS 的减少大部分来自额外缓存。

1.3 一维数据集中的稀疏数据

Quora 在缓存方面经常遇到的另一个问题是:稀疏一维数据集。如可能需要查询数据库,看某问题是否需重定向到另一问题(如同一个问题被重新发布,就可能发生这种情况)。

绝大多问题不需要重定向,所以 Quora 只会获取几个“重定向”,而大量“不重定向”。

当他们只是缓存了 question_id ,缓存中就会填满不用,只有几个重定向。 这在缓存中占用大量空间,且由于“重定向”数量如此稀疏,也会导致大量缓存未命中。

相反,他们开始缓存范围。 如 question id 123–127的任一问题都没重定向,那么他们会将该范围缓存为所有问题均为 No,而不是缓存每个单独的 question id。

这大大降低此类查询的数据库负载,QPS 下降 90%。

2 优化表占用空间

由于以下几个原因,表大小很重要:

  • 存储更多数据的成本更高
  • 随表增长,适应数据库缓冲池的数据百分比会变小,即IO会逐渐增加,性能会逐渐下降
  • 备份和恢复时间会随表大小线性增长。虽然备份是从 MySQL 副本完成的,但我们也会从副本读数据。在备份期间,MySQL副本性能略有下降
  • 随表增长,备份大小也在增长,导致备份存储成本随时间增长

显然,对不需要永久存储的数据,制定最佳保留策略有助减少表大小 —— 使用 MyRocks 减少表大小

  • 有一些表对于表所有者来说无法接受任何数据的删除。为此研究使用 MyRocks 来减小空间使用
  • MySQL 中的表可能使用更复杂的模式和查询。 所以他们希望谨慎使用 MyRocks。 作为分片项目的一部分,已对 MySQL 中最大的表进行分片,这是在 MySQL 在 Quora 的分片中记录
  • 此表是基于自增列范围进行分片的,与基于时间的分片接近,因为自增列值随时间增加
  • 大多数查询访问最近的分片。 包含 18 个月以上旧数据的较旧分片对日常业务相对不太关键

因此,他们决定按如下方式将较旧的分片移至 MyRocks。 有个工具可将 MySQL 表从一个 MySQL 主服务器移动到另一个主服务器。 每个分片实际上是一个 MySQL 表。 他们能够使用该工具按如下方式将包含旧数据的 MySQL 分片转换为 MyRocks 分片:

  • 在 MyRocks 主服务器上使用相同的模式创建一个新的空表,但使用 RocksDB 存储引擎
  • 使用该工具复制数据并从 MySQL 主服务器重放binlog(二进制日志)到 MyRocks 主服务器。 (该工具已被修改为跳过在目标主机上创建表,因为它已经在前一步中创建过。)
  • 执行阴影读取测试以验证 MyRocks 分片返回的结果与 MySQL 分片的结果相同。
  • 将流量切换到 MyRocks 分片。 (这类似于我们在将 MySQL 表从一个 MySQL 主服务器移动到另一个 MySQL 主服务器时执行的切换。 源主机上的表被重命名以停止新写入,然后在重放赶上后,该表的流量会切换到目标主机。)
  • 对于非键值存储表使用 MyRocks 是我们的一个重大举措。 根据表的不同,空间使用量的减少也有差异。 对于上面提到的第一个表,我们看到每个已移动的分片使用的空间减少了 80% 以上! 对于第二个表,我们看到每个已移动的分片使用的空间只减少了约 50-60%

3 优化写入

有时复制延迟警报,因为 MySQL复制默认情况下会在副本上串行重放主服务器上的并发写。在主服务器上并行写入而在副本上串行重放写入并不适合扩展写入,特别是如果他们使用带多核 CPU 的机器。

MySQL 提供两种方法实现这点,如下所述。两种方法中都需使用 slave_parallel_workers 配置并行度。

  1. slave_parallel_type=LOGICAL_CLOCK(从 MySQL 8.0.26 开始为 replica_parallel_type)
  • MySQL 5.7开始可用。即使所有表都在同一逻辑数据库中,它也可以在副本上并行执行写。
  1. slave_parallel_type=DATABASE(从 MySQL 8.0.26 开始为 replica_parallel_type)
  • 这需要表位于多个逻辑数据库中才能并行执行写
  • 增强存储在 zk 中的数据库配置,以跟踪表所在的逻辑数据库。将此信息保存在 zk 而非代码库或静态配置中,允许动态更改现有表的逻辑数据库。大多数表都位于默认逻辑数据库,因此只需要为不在默认逻辑数据库中的表保留此信息
  • MySQL alter table 语句可用于更改表的逻辑数据库,如 alter table <logical_db1>.table rename <logical_db2>.mytable。 它不复制数据,只是将底层 ibd 文件从一个目录移动到另一个目录,速度很快。移动表后,我们还会在 zk 更新数据库配置,以便应用程序可找到该表
  • 他们将一个表移动到其自己的逻辑数据库并启用并行复制。有助减少包含该表的 MySQL 副本上的复制延迟。

4 结论

学习了世界级大厂如何使用各种技术的组合来优化数据库中的读取、写入和空间使用。你们公司如何优化的呢?欢迎和我一起交流。

参考:

  • https://www.percona.com/blog/scaling-mysql-a-good-problem-to-have

    本文由博客一文多发平台 OpenWrite 发布!

相关文章:

顶级大厂Quora如何优化数据库性能?

Quora 的流量涉及大量阅读而非写入&#xff0c;一直致力于优化读和数据量而非写。 0 数据库负载的主要部分 读取数据量写入 1 优化读取 1.1 不同类型的读需要不同优化 ① 复杂查询&#xff0c;如连接、聚合等 在查询计数已成为问题的情况下&#xff0c;它们在另一个表中构…...

Java第二十章多线程

一、线程简介 线程是操作系统能够进行运算调度的最小单位&#xff0c;它被包含在进程之中&#xff0c;是进程中的实际运作单位。一个进程可以包含多个线程&#xff0c;这些线程可以并发执行。线程拥有自己的栈和局部变量&#xff0c;但是它们共享进程的其他资源&#xff0c;如…...

家庭教育,培养娃什么最重要?

家庭教育&#xff0c;培养娃什么最重要&#xff1f; 培养能力最重要 &#xff08;我这么认为的&#xff09; 时代巨变&#xff0c;技术变革的非常快&#xff0c;所以总的来说 年轻一代接触的新东西慢慢比老一代的要多&#xff0c;年轻一代的工作会比老一代的多而且多很多&…...

Linux 进程(一)

1 操作系统 概念&#xff1a;任何计算机系统都包含一个基本的程序集合&#xff0c;称为操作系统(OS)。笼统的理解&#xff0c;操作系统包括 内核&#xff08;进程管理&#xff0c;内存管理&#xff0c;文件管理&#xff0c;驱动管理&#xff09; 其他程序&#xff08;例…...

vue中的keep-alive详解与应用场景

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;Vue篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来vue篇专栏内容:vue-keep-alive 目录 一、Keep-alive 是什么 二、使用场景 三、原理分析 四、案例实现 activa…...

软件设计师——程序设计语言基础(一)

&#x1f4d1;前言 本文主要是【程序设计语言基础】——程序设计语言基础的相关题目&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &#…...

Apache简介与安装

先导概念: 静态网站: 最早的建站方式,每个页面都是一个独立的文件,需要手动上传或编辑。网页内容固定不变。例如,个人博客、静态企业官网等。 动态网站: 网站内容可根据不同情况动态变更,一般通过数据库进行架构。包含服务器端脚本,可以实现更丰富的功能。例如,社…...

set与map

set与map 一、序列式容器与关联式容器二、pair1、键值对2、作用3、构造函数4、make_pair&#xff08;1&#xff09;构造函数&#xff08;2&#xff09;作用 5、代码6、运行结果 三、set1、概念2、代码3、运行结果4、说明 四、multiset1、与set的关系2、代码3、运行结果 五、map…...

基于单片机智能液位水位监测控制系统

**单片机设计介绍&#xff0c; 基于单片机智能液位水位监测控制系统 文章目录 一 概要特点应用场景工作原理实现方式 系统功能实时监测控制调节报警功能数据记录与分析 总结 二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 ## 系统介绍 基于单片机…...

C#,《小白学程序》第十七课:随机数(Random)第四,移动平均值(Moving Average)的计算方法与代码

1 文本格式 /// <summary> /// 《小白学程序》第十七课&#xff1a;随机数&#xff08;Random&#xff09;第四&#xff0c;移动平均值的计算方法与代码 /// 继续学习数据统计&#xff0c;移动平均值的计算方法 /// 移动平均值就是一定步长内数值的平均值&#xff0c;用…...

行情分析——加密货币市场大盘走势(11.29)

大饼已经形成了底背离&#xff0c;即MACD往下走&#xff0c;而价格还在往上走&#xff0c;这种后续往往会大跌。继续把空单拿好&#xff0c;已经持仓的无需加仓。多次上涨却一直不能突破&#xff0c;说明多空和空军力量都很强&#xff0c;等待后续出方向。在笔者看来&#xff0…...

C++——string的字符串比较,字符存取,插入和删除和子串

一. string字符串比较 功能描述:字符串之间的比较 比较方式:字符串比较是按字符的ASCII码进行对比 返回 0 > 返回 1 < 返回 -1 函数原型: *int compare(const string &s) const; //与字符串s比较 *int compare(const char *s) const; //…...

字节10年经验之谈 —— 从0到1开发自动化测试框架!

一、序言 随着项目版本的快速迭代、APP测试有以下几个特点&#xff1a; 首先&#xff0c;功能点多且细&#xff0c;测试工作量大&#xff0c;容易遗漏&#xff1b;其次&#xff0c;代码模块常改动&#xff0c;回归测试很频繁&#xff0c;测试重复低效&#xff1b;最后&#x…...

Mysql(基本介绍+下载安装+服务器+基本使用+建库建表+navicat/mybitas工具+外键及实例)

一、Mysql基本介绍 当谈论MySQL时&#xff0c;通常指的是一个流行的开源关系型数据库管理系统&#xff08;RDBMS&#xff09;。MySQL是由瑞典的开发者在1995年创建的&#xff0c;后来被Sun Microsystems收购&#xff0c;最终成为Oracle Corporation的一部分。以下是关于MySQL的…...

Python+requests+Jenkins接口自动化测试实例

在做功能测试的基础上&#xff0c;我平时也会用postman测试接口&#xff0c;不过postman只能测试一个一个接口&#xff0c;不能连贯起来&#xff0c;特别是我们公司的接口很多都是要用到token的&#xff0c;导致我每次测个需要登录的接口都要去获取到token&#xff0c;做了很多…...

SpringBoot3核心原理

SpringBoot3核心原理 事件和监听器 生命周期监听 场景&#xff1a;监听应用的生命周期 可以通过下面步骤自定义SpringApplicationRunListener来监听事件。 ①、编写SpringApplicationRunListener实现类 ②、在META-INF/spring.factories中配置org.springframework.boot.Sprin…...

JS常用数据类型转换(数字型和字符串型之间转换)

提供了5中基本数据类型&#xff1a;数字 number 字符串 string 布尔 boolean 空值 null 未定义的 undefined 常用的是数字型和字符串型之间的转换&#xff0c;常用的转换方法如下&#xff1a; 1 数字型转换成字符串型 a) 使用String&#xff08;&#xff09;方法…...

算法通关村第一关—青铜挑战—用Java基本实现各种链表操作

文章目录 第一关—链表【青铜挑战】1.1 单链表的概念1.2 链表的相关概念1.3 创建链表 - Java实现1.4 链表的增删改查1.4.1 遍历单链表 - 求单链表长度1.4.2 链表插入 - 三种位置插入&#xff08;1&#xff09;在链表的表头插入&#xff08;2&#xff09;在链表的中间插入&#…...

SparkRDD及算子-python版

RDD相关知识 RDD介绍 RDD 是Spark的核心抽象&#xff0c;即 弹性分布式数据集&#xff08;residenta distributed dataset&#xff09;。代表一个不可变&#xff0c;可分区&#xff0c;里面元素可并行计算的集合。其具有数据流模型的特点&#xff1a;自动容错&#xff0c;位置…...

嵌入式设备与PC上位机通信协议设计的几点原则

嵌入式设备在运行中需要设置参数&#xff0c;这个工作经常由PC机来实现&#xff0c;需要为双方通信设计协议&#xff0c;有代表性协议是如下三种&#xff1a; 从上表可以看到&#xff0c;一般嵌入式设备内存和运算性能都有限&#xff0c;因此固定二进制是首选通信协议。 一&am…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

渲染学进阶内容——模型

最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建

华为云FlexusDeepSeek征文&#xff5c;DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色&#xff0c;华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型&#xff0c;能助力我们轻松驾驭 DeepSeek-V3/R1&#xff0c;本文中将分享如何…...

AI,如何重构理解、匹配与决策?

AI 时代&#xff0c;我们如何理解消费&#xff1f; 作者&#xff5c;王彬 封面&#xff5c;Unplash 人们通过信息理解世界。 曾几何时&#xff0c;PC 与移动互联网重塑了人们的购物路径&#xff1a;信息变得唾手可得&#xff0c;商品决策变得高度依赖内容。 但 AI 时代的来…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf

FTP 客服管理系统 实现kefu123登录&#xff0c;不允许匿名访问&#xff0c;kefu只能访问/data/kefu目录&#xff0c;不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)

引言 在人工智能飞速发展的今天&#xff0c;大语言模型&#xff08;Large Language Models, LLMs&#xff09;已成为技术领域的焦点。从智能写作到代码生成&#xff0c;LLM 的应用场景不断扩展&#xff0c;深刻改变了我们的工作和生活方式。然而&#xff0c;理解这些模型的内部…...

MinIO Docker 部署:仅开放一个端口

MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...

倒装芯片凸点成型工艺

UBM&#xff08;Under Bump Metallization&#xff09;与Bump&#xff08;焊球&#xff09;形成工艺流程。我们可以将整张流程图分为三大阶段来理解&#xff1a; &#x1f527; 一、UBM&#xff08;Under Bump Metallization&#xff09;工艺流程&#xff08;黄色区域&#xff…...

【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅!

【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅! 🌱 前言:一棵树的浪漫,从数组开始说起 程序员的世界里,数组是最常见的基本结构之一,几乎每种语言、每种算法都少不了它。可你有没有想过,一组看似“线性排列”的有序数组,竟然可以**“长”成一棵平衡的二…...