手机端网站源码,wordpress调用文章标题,企业网站建设优化,网站详情页用cdr做可以吗前言
大家好#xff01;在互联网时代#xff0c;我们的每一个动作#xff0c;无论是浏览网页、分享动态、点赞、购物或者搜索信息#xff0c;都会在背后产生数据。这些数据#xff0c;根据其用途和重要性#xff0c;可能会被储存到不同的地方#xff0c;其中最常见的存…前言
大家好在互联网时代我们的每一个动作无论是浏览网页、分享动态、点赞、购物或者搜索信息都会在背后产生数据。这些数据根据其用途和重要性可能会被储存到不同的地方其中最常见的存储载体就是——数据库。
不过数据库并非一成不变的。根据应用场景和数据特性我们有关系型数据库如MySQL也有非关系型数据库例如Redis。比如说当你在社交网络上点赞一条动态时为了快速响应可能是一个基于内存的数据库如Redis首先记录这一动作而后台可能会周期性地同步这些动作到持久化的存储系统中。
那么当面对巨大的数据流入时我们如何高效、稳定地将这些数据存储到数据库中呢“我每次应该插入多少数据才最合适” 这个问题尽管看似简单但涉及到的策略和技术都颇为丰富。
所以本文的目的就是带领大家一同探索这个话题。不论你是初涉数据库的新手还是有经验的开发者我都希望你能从这篇文章中获得有价值的信息。那么不再赘述我们现在就开始吧
说在开头
在开始讨论这个话提前我们先看面试场景中的对话 面试官: 在你之前的工作经验中当你们需要向数据库中插入大量数据时你们是如何操作的 候选者: 噢我们使用批量插入来优化性能。 面试官: 很好。那你们每次批量插入大约多少条数据 候选者: 通常我们每次批量插入超过2000万条数据。 面试官: 2000万条你确定每次都插入这么多数据不担心资源过载或事务延迟等问题吗 候选者: 我这系统插入2000w条数据没问题啊不信你可以回访我们Leader 面试官: 但是你有没有考虑过为什么2000w条数据可以2000w条数据是基于什么方式算出来的 候选者: 是不是数据量 面试官: 数据量只是其中一个因素。但2000万条数据对于不同的数据库配置、硬件环境、甚至数据本身的复杂性来说可能有不同的影响。只是简单地说“我们的系统可以处理”并不足以说明问题。真正的关键是你知道为什么你的系统可以处理这么大的数据量吗或者说你们是怎么确定2000万是一个合适的数字的 候选者: 呃...这个...我不太清楚是我们之前的一位资深工程师定的。 面试官: 这就是问题所在。我们在工作中不仅要知道如何做还要知道为什么这么做。只有了解背后的原理和策略我们才能更好地优化和应对各种问题。 候选者: 明白了我以后会注意这个问题。 面试官: 很好对于这个问题你可以回去深入研究一下。你先回去等通知。 从上面的对话中我们可以看到一个很现实的问题很多人可能知道批量插入可以提高性能但真正了解背后原因的却不多。而一个优秀的工程师应该不仅仅满足于“这样做可以工作”而是要探求背后的“为什么”。
所以为了不让你们变成上面的候选者在这篇文章中我们将深入探讨数据库插入的各种策略、技术以及背后的原理。不过在此之前我们还是得先了解一些基础。
数据库插入操作的基础知识
插入数据是数据库操作中的基础。但是我们程序员将面临随之而来的问题如何快速有效地插入数据并保持数据库性能当你向数据库中插入数据时这些数据直接存储到硬盘上吗
1.1 插入数据的原理
深入了解插入数据时背后发生的事情是优化数据库性能的关键。
1.1.1 写入缓存与磁盘同步
当数据被写入数据库时它首先应该被写入缓存中而不是缓慢的磁盘中。然后后台线程在适当的时间点将数据同步到磁盘上。
这样做的主要原因有以下几点 速度差异 RAM随机存取存储器的速度远远快于磁盘。RAM对数据的读写几乎是瞬时的。而磁盘无论是传统的机械硬盘还是现代的固态硬盘其读写速度都远慢于 RAM。 磁盘 I/O 的成本 每次进行磁盘 I/O操作都有一定的开销。如果数据库频繁地进行小批量的磁盘写入这会导致大量的 I/O 开销得不偿失哇。 合并写入 首先将数据写入 RAM在数据库可以把数据同步到磁盘之前累积多个写入操作。最后一次性将大量数据写入磁盘从而减少 I/O 操作的次数和开销。
总结: 总的来说嘛为了最大化性能数据库首先将数据写入缓存并在适当的时间点将这些数据同步到磁盘。这种策略不仅加速了写入操作还有效地减少了磁盘 I/O提高数据库性能。 那脏页还没有来得及刷入到磁盘时MySQL 宕机了数据不就莫得了 这我懂InnoDB 在进行更新操作时采用了 Write Ahead Log先写日志策略。这意味着在数据被写入磁盘之前相关的操作会首先被记录到 redo log 日志中。这种策略赋予了 MySQL 在系统崩溃后的恢复能力。 1.1.2 事务日志与数据持久化
为了确保数据的完整性数据库首先将插入操作写入事务日志。只有当数据被安全地写入日志后它才被移动到实际的数据表中。 那为什么数据库要用“页”来存储数据呢 我画个图你看下 没看出来啊你这基础还不错。 谢谢我接着往下说 1.2 数据存储单位页
操作系统为了管理物理内存和虚拟内存使用一个称为“页”的结构来管理说白了其实就是一块固定的连续内存空间而已。这些页有固定的大小如 4KB、8KB 或 16KB。这个大小一般是块的整数倍。
使用页进行存储有多种优势如减少磁盘I/O、高效的空间管理以及缓存优化。了解你的数据库页的大小可以帮助你优化插入操作和空间管理 那么单条数据插入和批量数据插入在速度和效率上有什么不同呢 1.3 单条数据与批量数据插入的差异
1.3.1 速度和效率比较 知识点我们的业务系统的CUD操作每次都要伴随着事务开销。如果你在应用中执行单条插入插入了1000次数据那么你就有1000次事务开销。而批量插入可以将这些数据在一个事务中插入大大减少了总的事务开销。
单条插入虽然简单明了但在大量数据插入时其性能上的缺陷会逐渐显现。与之相对批量插入可以显著提高性能但它也引入了其它问题数据的验证和错误处理变得更为复杂。鱼与熊掌不可兼得
1.3.2 对数据库性能的影响 小贴士批量插入可以减少磁盘I/O次数从而提高性能。但是如果一次插入的数据量过大它可能会暂时阻塞其他操作影响数据库的响应时间。
为了达到最佳性能您可能需要根据实际情况调整批量插入的数据量。过少的数据可能导致性能优化不足而过多的数据可能导致数据库响应时间增加。 数据库的锁机制和并发控制策略在插入操作中起到关键作用。如果多个进程或线程试图同时插入数据可能会发生锁争用进而影响性能。我们又该如何优化这些机制进一步提高批量插入的性能呢 如何决定合适的插入数据量
为了实现数据库的最大效能确定合适的插入数据量至关重要。但这并不是一项简单的任务需要考虑多种因素。 很好啊能考虑这个说明你有在思考了那当你决定插入一大批数据时你通常是如何选择具体的数量的 2.1 考虑硬件和系统资源
在考虑合适的插入数据量时首先需要考虑的是硬件和系统的限制。
磁盘I/O:
磁盘I/O是插入数据时的主要瓶颈之一。过多的插入操作会导致磁盘I/O饱和降低系统的响应时间。 优化建议监控磁盘I/O使用情况确保在高插入量时不超过其峰值。
内存使用:
大量的插入操作可能会增加RAM的使用量。如果内存使用接近或达到了系统限制可能会导致性能下降甚至导致系统崩溃。 小贴士定期检查系统的内存使用情况确保有足够的可用资源来处理大量的插入操作。
2.2 数据库的内部机制
数据库本身也有一些内部机制这些机制在决定插入数据量时也应该考虑。
事务大小
数据库事务的大小直接影响其性能。较大的事务可能会导致长时间的锁定从而影响其他查询的性能。 小贴士找到合适的事务大小平衡点是提高插入性能的关键。太小的事务可能会增加总的事务数量而太大的事务可能会导致系统资源的饱和。
锁策略
考虑到数据库的锁策略也很重要。过多的锁争用可能会导致性能下降。 深入探讨优化数据库的锁策略和并发控制可以进一步提高插入性能。 : 你先别管事务和锁的问题你是通过监控这些硬件性能去调整合适的插入量那生产怎么办没有可以估算的大小我不是很满意你这个回答你思考思考再回答我出去接个水。 : 这.....(拿起手机google).... 2.3 估算插入量
为了进行这个估算我们首先要确定一条记录的结构。假设我们有以下的记录结构 整型字段 (int): 4 字节 变长字符字段 (varchar): 假设平均长度为 50 字节最大长度为 255 字节 日期字段 (date): 3 字节 浮点数字段 (float): 4 字节
基于上述的结构一条记录的平均大小可以估算为 为了考虑到某些记录可能使用 varchar 的最大长度我们也可以计算最大记录大小 内存分析
假设给定 8G 内存并且预留 20% 的空间我们可以使用的内存为 由此我们可以存储的最大记录数为 硬盘分析
考虑 512G 硬盘我们可以存储的最大记录数为 : 差不多就这样为自己的计算沾沾自喜中 : 可以啊功底不错虽然有点瑕疵刮目相看这轮面试差不多就让你过了 实际应用中的策略与建议结合MyBatis : 上面说的都是理论你项目中一般怎么使用批量插入的 : 我想下啊 大概就这些点 使用foreach标签进行批量插入
在MyBatis的映射文件中通常使用foreach标签来进行批量插入。
insert idinsertMultiple parameterTypelistINSERT INTO tableName (column1, column2, ...)VALUESforeach collectionlist itemrecord separator,(#{record.column1}, #{record.column2}, ...)/foreach
/insertExecutorType.BATCH
Mybatis Plus也有相关的批量插入的方法。不过你也可以设置ExecutorType为BATCH来开启批处理模式。这样所有的SQL语句都会被积累直到手动提交或关闭会话。
SqlSession session sqlSessionFactory.openSession(ExecutorType.BATCH);使用BATCH模式时MyBatis允许你设置一个batchSize。累积到多少数量的SQL语句时MyBatis就会会将它们批量执行。合理设置batchSize可以避免OOMOut of Memory问题。一帮情况下我们项目组就是用这个办法怕有些新手程序员批量单条插入导致性能缓慢。
避免频繁的会话提交
在批量插入期间频繁提交会话可能会导致性能下降。一般在插入完所有数据后再进行一次会话提交。 : 大概就这些 : 好了解了 总结
最后我们来总结下扒。在本文中我为你提供一个参与面试的视角帮助你理解和优化数据库的插入操作。
不管你是数据库新手还是经验丰富的开发者我希望这些建议能够为你在实际应用中带来价值。感谢你的阅读如有任何疑问或建议请随时与我分享
参考文献 https://downloads.mysql.com/docs/refman-5.7-en.a4.pdf