在 MySQL InnoDB 中,ROW_FORMAT 的 COMPRESSED、COMPACT 和 DYNAMIC 有什么区别?
彼此之间有什么好处?
不久前我一直在阅读有关 MySQL 的文件格式 Antelope 和 Barracuda 的信息,我想知道我是否可以从拥有 Barracuda 和 Compression 中受益。
我的服务器目前正在使用 Antelope,因为它是 MySQL 的默认设置。
由于我拥有的大型数据库,我多次遇到内存问题。我的数据库每天都在增加。
似乎压缩正在为一些人带来好处,例如:http :
//www.mysqlperformanceblog.com/2008/04/23/real-life-use-case-for-barracuda-innodb-file-format/
我知道内存和磁盘空间可能会更低,但我不确定我是否理解这一点(引自文章):
“根据 top 约 5% CPU 负载(从 80-100% 主要等待 I/O)
0.01秒平均主键查找时间(转换前 1-20 秒)"
我认为这两件事不会改善,因为如果数据被压缩,服务器必须解压缩才能再次获得原始数据,那么CPU使用率会增加是否有意义?
这在读/写密集型应用程序中对您有好处吗?你会建议我改用 Barracuda 和 Compression 吗?
你知道梭子鱼的任何问题吗?
以下问题的答案似乎指出了一些问题,但由于它是 2011 年的,我想说它们现在已经修复:https : //serverfault.com/questions/258022/mysql-innodb-how-to-switch -到梭鱼格式
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 …
我有一个VARCHAR(80) utf8mb4
专栏,我正在测试添加一些 ASCII 和表情符号字符,并使用LENGTH()
和CHAR_LENGTH()
来理解差异。
通过阅读不同的地方,我的理解是,utf8mb4
列上的每个字符将占用 4 个字节。LENGTH()
然而,如果我理解为给我特定内容在该字段上的实际大小,情况似乎可能并非如此。
包含“aaaa”内容的行比包含“”的行占用的存储空间更少,这是否正确?
我实际上很难理解这里的问题。我到处都看到说 UPDATE 受益于 WHERE 子句上的索引。
然而,这个查询,
UPDATE `documents` SET `read`="1" WHERE `docid` IN (<subquery>)
Run Code Online (Sandbox Code Playgroud)
似乎没有使用索引。该表documents
有一个索引 ondocid
和 on read
。
当我执行 时EXPLAIN
,我看到possible_keys = NULL
和rows = 8011008
(全表)。子查询确实使用键并读取正确的行(2 行)。
另一方面,这个查询:
SELECT * FROM `documents` WHERE `docid` IN (<subquery>)
Run Code Online (Sandbox Code Playgroud)
确实使用索引docid
并且运行速度非常快。它读取的行数比需要的多(根据EXPLAIN
),但完全可以接受。
对此有什么解释吗?
我使用 MariaDB 10。
作为一个有趣的注释(关于SELECT
),如果在<subquery>
我使用 aUNION
时,虽然子查询似乎获得了正确的行数,但主查询似乎不使用索引并进行全表扫描。
如果在UPDATE
I useJOIN
而不是 中IN
,则索引被正确使用。我通过使用解决了我的问题JOIN
。
mysql ×5
innodb ×4
mariadb ×3
compression ×2
index ×2
mariadb-10.1 ×1
mariadb-10.5 ×1
mysql-8.0 ×1
partitioning ×1
utf-8 ×1