Nun*_*uno 9 mysql innodb mariadb index partitioning
PARTITION我目前正在探索, 对于我的特定用例的使用。
\n我使用 InnoDB,每个表一个文件。玛丽亚数据库 10.8。
我正在阅读 Rick 的PARTITION Maintenance in MySQL网页。
\n我想强调这一点:
\n\n\n\n
WHERE X = 1234-- 这使得“分区修剪”仅在该一个分区中查找。但这并不比INDEX(x)在非分区表上好。无论如何,您可能都需要该索引;在第一次“修剪”到所需的分区后,您仍然需要索引。没有更快。
\n一个常见的谬误:“分区将使我的查询运行得更快”。不会的。思考“点查询”需要什么。没有分区,但有适当的索引,有一个 BTree(索引)可以向下钻取以找到所需的行。对于 10 亿行,这可能是 5 层深。通过分区,首先选择并“打开”分区,然后向下钻取较小的 BTree(例如 4 层)。嗯,较浅 BTree 的节省被必须打开分区所消耗。同样,如果您查看需要访问的磁盘块,以及其中哪些块可能会被缓存,您会得出结论:可能有大约相同数量的磁盘命中。由于磁盘命中是查询中的主要成本,因此分区不会获得任何性能(至少对于这种典型情况)。二维情况(如下)给出了该讨论的主要矛盾。
我完全明白这意味着什么,但我有一个问题:
\n在 MySQL/MariaDB 中,索引的性能会随着索引变得越来越大而降低吗?
\n对于 10 亿行或 1000 亿行,就性能而言,好的索引总是优于分区吗?
\n--
\n还有一点最接近我想要受益的:
\n\n\n用例#3——热点。这个解释起来有点复杂。给定以下组合:
\n
\n\xe2\x9a\x88 表的索引太大而无法缓存,但一个分区的索引是可缓存的,并且
\n\xe2\x9a\x88 索引是随机访问的,并且
\n\xe2\x9a\x88 由于更新索引,数据摄取通常会受到 I/O 限制
\n分区可以将所有索引保持在 RAM 中“热”,从而避免大量 I/O。案例 3 的重大胜利:改进缓存以减少 I/O,从而加快操作速度。
\n
“索引缓存”对 InnoDB 也有效吗?我的理解CACHE INDEX只适用于MyISAM。
\n或者这与它在 InnoDB 缓冲池中有关吗?
关于减少 I/O,这是否适用于 NVMe 服务器?我的%iowait是 0.00,而我的应用程序是写入密集型的。
Bil*_*win 10
对于 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/
通过将索引页的子集保留在 RAM 和 InnoDB 缓冲池中,可以降低 I/O 成本。但是,如果索引增长得比 RAM 大得多,则没有足够的缓冲池来容纳整个索引,因此如果您在整个索引上随机搜索,InnoDB 可能会逐出您很快将再次需要的页面。当您需要这些页面时,它们会从存储中重新加载,但这可能会导致页面在 RAM 中换入和换出时产生额外的开销。
缓存索引仅适用于MyISAM。InnoDB 按需缓存页面,其中可能包括给定索引的子集。忘记任何将索引加载到缓存中的手动命令。老实说,我建议出于任何目的忘记 MyISAM。自 2000 年代以来,我还没有看到它得到适当的使用。
您询问了 NVMe 存储。NVMe 当然比旧的 SATA 接口更快,但它与 RAM 相比如何?这取决于您测量的内容,但就访问时间和吞吐量(MB/秒)而言,您可以信赖 RAM 比最新一代 NVMe 快数倍。此外,编写 InnoDB 代码时假设页面必须位于 RAM 中才能读取。将数据和索引页缓存在 RAM 中仍然是一个胜利。
我同意 Rick 的总体说法,即分区通常不会像您想象的那样对性能有帮助。它在正确的场景中很有用,但它并不是一个神奇的“一切都很快”的解决方案。对于所有其他类型的优化也是如此!
(除了比尔的评论......)
另一种分析性能的方法——“计算磁盘命中数”。
(在最后两句话中我做了很多“挥手”。)
我希望我已经为您提供了一些线索,帮助您自行判断您的桌子是否会随着其增长而受到影响。如果您想进一步讨论,请提供CREATE TABLE。当有人谈论十亿行表时,我喜欢缩小数据类型、重构架构、规范化、添加汇总表、考虑分片等。但我很少推荐分区。有时,我建议“保留汇总表,但扔掉事实表”。这消除了各种扩展和性能问题。
在 MySQL/MariaDB 中,索引的性能会随着索引变得越来越大而降低吗?
这取决于你所说的“性能”是什么意思......
如果您的意思是“根据索引键查找一行或一系列行”,那么答案将是“一点点”。正如其他人所解释的,只要索引的工作集保留在缓存中,“大”可能会比“小”慢一点,但这很可能会被物流、网络使用的其余查询时间淹没如果叶页没有被缓存,那么就会添加一个随机 IO,所以你必须询问你的 IO 系统这需要多长时间。
但是您询问索引与分区,因此在这种情况下,如果“分区”情况和“单表”情况下的数据相同,则分区上索引的总大小将与索引几乎相同在单人桌子上。在相同的查询负载下,没有理由认为其中一个会比另一个更好地缓存,因此两者之间可能没有区别。如果您只访问最新的行,那么这两种情况都会以同样的方式受益,因为只需要缓存索引的相应部分。
但是,如果您从全局角度考虑性能并添加诸如“删除超过 12 个月的所有行”之类的内容,并且在运行此归档操作时要删除 10 亿行,那么巨大的表和巨大的索引将成为一个极其糟糕的主意(TM )。如果它是日期索引,也许它是可以容忍的,因为删除将触及它的连续块。然而,如果它是一个相当随机的列上的索引,那么每个删除的行都会触发索引中某个地方的随机写入,整个地方,这将永远令人烦恼。
然而,如果您使用分区,“DROP PARTITION”几乎是瞬时的,因为在幕后,它只是删除相应的文件。除非要触发 ON DELETE 触发器,否则如果数据库知道我们要删除整个分区,则读取要删除的行是没有意义的。
如果没有对旧分区进行写入,如果备份工具可以利用不需要备份未更改的分区这一事实,则备份速度可能会快得多。
我正在编辑添加分区可以使查询更快的其他情况:
您没有足够的钱将整个表放在 SSD 上,因此您将很少访问的旧分区(和索引)放在笨重、缓慢旋转的 RAID 上,以及查看大部分数据的最新分区(和索引)。在一些非常快的 SSD 上的操作。这是一个很好的“现金与性能”优化,但您将不得不偶尔移动分区。也许您甚至可以只复制最近的分区,或者为每个服务器放置一个分区并并行运行它们(如果数据库支持的话),诸如此类。
此外,如果查询优化器搞砸了并决定进行全表扫描或类似的操作,也许如果您的表已分区并且查询对分区键有一个条件,则搞砸的大小可以限制为仅一个几个分区而不是整个表。
| 归档时间: |
|
| 查看次数: |
2854 次 |
| 最近记录: |