AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 321514
Accepted
Nuno
Nuno
Asked: 2022-12-29 16:47:10 +0800 CST2022-12-29 16:47:10 +0800 CST 2022-12-29 16:47:10 +0800 CST

在 MySQL/MariaDB 中,Indexes 的性能会随着越来越大而下降吗?

  • 772

我目前正在探索PARTITION, 对于我拥有的特定用例的使用。
我使用 InnoDB,每个表的文件。玛丽亚数据库 10.8。

我在 MySQL网页上阅读了 Rick 的PARTITION Maintenance 。

我想强调这一点:

WHERE X = 1234-- 这让“分区修剪”只在那个分区中查看。但这并不比INDEX(x)在非分区表上好。而且您可能无论如何都需要该索引;在第一次“修剪”到所需的分区后,您仍然需要索引。没有更快。
一个常见的谬误:“分区将使我的查询运行得更快”。它不会。思考“点查询”需要什么。没有分区,但有适当的索引,有一个 BTree(索引)可以向下钻取以找到所需的行。对于十亿行,这可能有 5 层深。对于分区,首先选择并“打开”分区,然后向下钻取较小的 BTree(比如 4 层)。嗯,较浅的 BTree 的节省被必须打开分区消耗掉了。类似地,如果您查看需要触及的磁盘块,以及其中哪些可能被缓存,您会得出结论,即可能有大约相同数量的磁盘命中。由于磁盘命中是查询的主要成本,因此分区不会获得任何性能(至少对于这种典型情况)。

我完全明白这意味着什么,但我有一个问题:

在 MySQL/MariaDB 中,Indexes 的性能会随着越来越大而下降吗?

对于 10 亿行或 1000 亿行,就性能而言,好的索引是否总是比分区更好?

--

还有一点最接近我想要受益的:

用例#3——热点。这个解释起来有点复杂。鉴于这种组合:
⚈ 一个表的索引太大而无法缓存,但一个分区的索引是可缓存的,并且
⚈ 索引是随机访问的,并且
⚈ 由于更新索引,数据摄取通常是 I/O 绑定
分区可以在 RAM 中保持所有索引“热”,从而避免大量 I/O。

案例 #3 的重大胜利:改进缓存以减少 I/O 以加速操作。

“索引缓存”对 InnoDB 也有效吗?我的理解CACHE INDEX只适用于MyISAM。
或者这是否与它在 InnoDB 缓冲池中有关?

关于减少 I/O,这是否适用于 NVMe 服务器?我%iowait的是 0.00,而我的应用程序是写密集型的。

mysql
  • 3 3 个回答
  • 1426 Views

3 个回答

  • Voted
  1. Bill Karwin
    2022-12-29T17:36:24+08:002022-12-29T17:36:24+08:00

    对于 10 亿行或 1000 亿行,就性能而言,好的索引是否总是比分区更好?

    关于这一点我可以说几件事。

    • 我们不能做出这种概括,因为它取决于查询。总的来说,每一种优化都是对正确类型查询的极大帮助,而牺牲了其他类型的查询。因此,在选择优化方法之前,您必须非常具体地了解要优化的查询。

    • 这不是一个非此即彼的选择。您可以对表进行分区,还可以定义索引,以便在给定分区中优化搜索。

    • 我不认为你有 1000 亿行。如果你这样做了,你就不会在 Stack Exchange 上问这个问题,你会分配给你的全职数据库架构师团队优化它的任务。他们无疑会带着使用许多服务器的设计回来。在单个表中存储 1000 亿行是不切实际的。你会如何备份它?你会如何添加一列?

    InnoDB 使用 B 树索引(也是全文索引和空间索引,但对于本次讨论,我们假设索引的默认类型)。

    B 树索引的插入和搜索复杂度均为O(log 2 n ),其中n是数据结构中的条目数。因此,随着索引变大,插入或搜索的开销会越来越大。

    索引搜索所需的 I/O 是B 树深度的函数。即要遍历多少层非终端节点才能到达叶节点。深度取决于有多少索引条目,还取决于给定条目的数据类型有多大,因为 InnoDB 页面大小是固定的,所以一个页面只能容纳这么多索引节点。请参阅: https ://www.percona.com/blog/2009/04/28/the_depth_of_a_b_tree/

    通过将索引页的子集保存在 InnoDB 缓冲池中的 RAM 中,可以减轻 I/O 成本。但是如果索引的增长比 RAM 大得多,则没有足够的缓冲池来容纳整个索引,因此如果您在整个索引上随机搜索,InnoDB 可能会驱逐您很快将再次需要的页面。这些页面将在您需要时从存储中重新加载,但这可能会导致额外的开销,因为页面会在 RAM 中换入和换出。

    缓存索引只适用于 MyISAM。InnoDB 按需缓存页面,其中可能包含给定索引的子集。忘记任何将索引加载到缓存中的手动命令。老实说,我建议出于任何目的忘记 MyISAM。自 2000 年代以来,我还没有看到它被适当地使用过。

    您询问了 NVMe 存储。NVMe 当然比旧的 SATA 接口更快,但它与 RAM 相比如何呢?这取决于您测量的内容,但对于访问时间和吞吐量(MB/秒),您可以指望 RAM 比最新一代 NVMe 快几倍。InnoDB 代码也被编写为假设页面必须在 RAM 中才能被读取。将数据和索引页缓存在 RAM 中仍然是一个胜利。

    我同意 Rick 的一般性说法,即分区通常不会像您认为的那样对性能有很大帮助。它在正确的场景中很有用,但它并不是一个神奇的“一切都很快”的解决方案。所有其他类型的优化也是如此!

    • 10
  2. Best Answer
    Rick James
    2022-12-29T21:04:12+08:002022-12-29T21:04:12+08:00

    (除了比尔的评论......)

    另一种分析性能的方法——“计算磁盘命中率”。

    • InnoDB 在其 buffer_pool 中缓存 16KB 的块(数据和索引)。
    • 缓存是按需的,并且大致是最近最少使用的。
    • 所有活动(读取、写入、查找等)都在 buffer_pool 中完成,而不是直接在磁盘上完成。
    • 一个简单的经验法则是任何 InnoDB BTree 的扇出大约为 100。(Percona 使用 128——基本上相同。)十亿行(数据或索引)将有 5 个级别。这意味着必须获取 5 个块(如果尚未缓存)来执行简单的点查询。或者通过辅助键查找 10 个块。(6 和 12 代表 1000 亿行。)
    • 如果要从该 BTree 获取 101 个“连续”行,则需要 2 个叶节点(开始的那个加上下一个)。另一个经验法则:所有非叶节点都可能被缓存。
    • 如果您的活动是随机的(例如 PK 的 UUID 或散列)并且buffer_pool 不能容纳整个 BTree,则缓存几乎变得毫无用处。这导致每个点查询至少命中 1 个磁盘。在这种情况下,“太大不利于性能”。
    • 另一方面,如果您只接触“最近”的行(并且 PK 是 AUTO_INCREMENT 或基于时间的),那么缓存 buffer_pool 在 100 次中有 99 次具有所需的数据。也就是说,基本上没有降级,因为table 增长,即使比 buffer_pool 大得多。

    (我在最后两个陈述中做了很多“挥手”。)

    我希望我已经给了你一些线索,让你自己判断你的桌子是否会随着它的增长而受到影响。如果您想进一步讨论,请提供CREATE TABLE. 当有人谈论 bilion-row 表时,我喜欢缩小数据类型、重构架构、规范化、添加汇总表、考虑分片等。但我很少推荐分区。有时,我建议“保留汇总表,但扔掉事实表”。这消除了各种缩放和性能问题。

    • 9
  3. bobflux
    2022-12-30T04:45:29+08:002022-12-30T04:45:29+08:00

    在 MySQL/MariaDB 中,Indexes 的性能会随着越来越大而下降吗?

    这取决于你所说的“性能”是什么意思......

    如果您的意思是“根据索引键查找一行或一系列行”,那么答案将是“一点点”。正如其他人所解释的那样,只要索引的工作集保留在缓存中,“大”可能会比“小”慢一点,但这很可能被物流、网络使用的其余查询时间所淹没,解析等。如果没有缓存叶子页面,那将添加一个随机 IO,因此您必须询问您的 IO 系统这需要多长时间。

    但是您询问索引与分区,所以在这种情况下,如果数据在“分区”情况和“单表”情况下相同,则分区上索引的总大小将与索引几乎相同单人桌上。对于相同的查询负载,没有理由比另一个缓存得更好,因此两者之间可能没有区别。如果您只访问最新的行,那么这两种情况都将以同样的方式受益,因为只需要缓存索引的相应部分。

    但是,如果您从全局的角度看待性能并添加诸如“删除所有早于 12 个月的行”之类的内容,并且在运行此归档操作时您有十亿行要删除,那么巨大的表和巨大的索引将成为一个极其糟糕的主意(TM ). 如果它是一个日期索引,也许它是可以容忍的,因为删除会命中它的一个连续块。但是,如果它是一个相当随机的列上的索引,那么每个删除的行都会触发索引中某个地方的随机写入,到处都是,这将永远存在。

    然而,如果您使用分区,“DROP PARTITION”几乎是瞬间的,因为在幕后,它只是删除相应的文件。除非有要触发的 ON DELETE 触发器,否则如果数据库知道我们要删除整个分区,那么即使读取要删除的行也毫无意义。

    如果没有对旧分区的写入,这可能会使备份更快,如果备份工具可以利用不需要备份未更改的分区这一事实。

    当分区可以使您的查询更快时,我正在编辑以添加其他情况:

    您没有足够的钱将整个表放在 SSD 上,因此您将很少访问的旧分区(和索引)放在笨重的慢速旋转 RAID 上,而最近的分区(和索引)可以看到大部分内容对某些快速 SSD 的操作。这是一个很好的“现金与性能”优化,但您必须偶尔移动分区。也许你甚至可以只复制最近的分区,或者在每个服务器上放置一个分区并并行运行它们,如果数据库支持的话,诸如此类。

    此外,如果查询优化器搞砸了并决定进行全表扫描或类似的事情,也许如果您的表已分区并且查询对分区键有条件,则搞砸的大小可以限制为仅几个分区而不是整个表。

    • 5

相关问题

  • 是否有任何 MySQL 基准测试工具?[关闭]

  • 我在哪里可以找到mysql慢日志?

  • 如何优化大型数据库的 mysqldump?

  • 什么时候是使用 MariaDB 而不是 MySQL 的合适时机,为什么?

  • 组如何跟踪数据库架构更改?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve