MySQL 中的解耦表提高了多少性能?
How much does decoupling tables in MySQL improve performance?
我正在设计数据库以在 MySQL 中存储一些博文。我最近 运行 浏览了这个 answer 它建议当你有:
- A table 将被定期查询(例如博客文章列表),但是
- 其中的一列 table 包含大量不会定期访问的数据(博客内容)
然后,如果您将内容存储在单独的 table 中,性能会更好,因此当您生成列表时,速度会更快。
CREATE TABLE article (
id INT(10) UNSIGNED,
title VARCHAR(40),
author_id INT(10) UNIGNED,
created DATETIME,
modified DATETIME
);
CREATE TABLE article_text (
id INT(10) UNSIGNED,
body TEXT
);
即使列不是查询的一部分,这是否会影响性能:
SELECT id, title FROM article WHERE author_id=33 ORDER BY created DESC LIMIT 5
它会在多大程度上成为性能问题? (几百、几千?几百万?)
对你所有的问题都是肯定的。
"Vertical partitioning"(构建 "parallel table")在并不总是需要 TEXT
(或 BLOB
等)时很有用。
当您不需要 TEXT
时,它的性能会更好,因为 table。
当您确实需要 TEXT
时,您可能只会获取一行(或很少的几行),因此 JOIN
到额外的 table 中的开销并不明显。
我有两个数据库,每个数据库有 20 万行,就这样拆分。两者都缩放得很好。我希望数百万甚至数十亿都没有问题。 (好吧,"billions" 有很多问题,但垂直分区是解决方案之一。)
您的示例 SELECT
需要 'compound' `INDEX(author_id, created) 才能扩展。但这与垂直分区无关。
在 MySQL 5.5 及更高版本中,InnoDB 存储引擎支持 Barracuda file format。为了使用 InnoDB 的 Barracuda 文件格式,你必须使用 file-per-table tablespace,或者使用通用的 table space (单文件 "system" InnoDB tablespace 不支持 Barracuda)。
在 Barracuda(羚羊)之前,MySQL always stored at least the first 768 bytes of a TEXT column in the clustered (primary key) index。在这种情况下,即使没有引用 TEXT 列,也会增加聚集索引(叶节点)中每一行的大小。这减慢了 table 对其他非 TEXT 列的扫描速度,因为每页适合的页面较少(平均要扫描更多页面以找到您要查找的内容),但在扫描 TEXT 列(第一个768 字节)。您是否经常进行 table 扫描?希望您能够使用索引来避免 table 扫描。
索引是 b-trees 并且键搜索在内部节点完成,其中只包含键。对于聚簇索引,那只是主键,所以聚簇索引搜索不受叶节点中数据量的影响(但受主键大小影响)。
对于 InnoDB 的 Barracuda 文件系统,整个 TEXT 列存储在溢出页中(可以压缩)。它的任何部分都不存储在聚集索引(叶节点)中。因此,如果您使用的是 Barracuda 文件系统,让 MySQL 为您进行分离,并将 TEXT 列放在相同的 table 中。在这种情况下,您没有任何收获,因为 MYSQL 已经将 TEXT 列放在其他地方并且不会影响扫描非 TEXT 列。
如果您正在使用 Antelope,如果您经常扫描非 TEXT 列(无论如何都应该避免),并且您很少引用 TEXT 列,则可以考虑拆分它。将其拆分为两个 tables,要读取整个记录,您现在必须在两个聚簇索引上进行搜索,这是一个的两倍。
我还可以看到想要在 MySQL 的 InnoDB 缓冲区 space 的 RAM 有限的系统上将其与 Antelope 拆分,并且您很少引用 TEXT 列。包含非 TEXT 列的叶节点如果较小,则更有可能保留在内存中。
我正在设计数据库以在 MySQL 中存储一些博文。我最近 运行 浏览了这个 answer 它建议当你有:
- A table 将被定期查询(例如博客文章列表),但是
- 其中的一列 table 包含大量不会定期访问的数据(博客内容)
然后,如果您将内容存储在单独的 table 中,性能会更好,因此当您生成列表时,速度会更快。
CREATE TABLE article (
id INT(10) UNSIGNED,
title VARCHAR(40),
author_id INT(10) UNIGNED,
created DATETIME,
modified DATETIME
);
CREATE TABLE article_text (
id INT(10) UNSIGNED,
body TEXT
);
即使列不是查询的一部分,这是否会影响性能:
SELECT id, title FROM article WHERE author_id=33 ORDER BY created DESC LIMIT 5
它会在多大程度上成为性能问题? (几百、几千?几百万?)
对你所有的问题都是肯定的。
"Vertical partitioning"(构建 "parallel table")在并不总是需要 TEXT
(或 BLOB
等)时很有用。
当您不需要 TEXT
时,它的性能会更好,因为 table。
当您确实需要 TEXT
时,您可能只会获取一行(或很少的几行),因此 JOIN
到额外的 table 中的开销并不明显。
我有两个数据库,每个数据库有 20 万行,就这样拆分。两者都缩放得很好。我希望数百万甚至数十亿都没有问题。 (好吧,"billions" 有很多问题,但垂直分区是解决方案之一。)
您的示例 SELECT
需要 'compound' `INDEX(author_id, created) 才能扩展。但这与垂直分区无关。
在 MySQL 5.5 及更高版本中,InnoDB 存储引擎支持 Barracuda file format。为了使用 InnoDB 的 Barracuda 文件格式,你必须使用 file-per-table tablespace,或者使用通用的 table space (单文件 "system" InnoDB tablespace 不支持 Barracuda)。
在 Barracuda(羚羊)之前,MySQL always stored at least the first 768 bytes of a TEXT column in the clustered (primary key) index。在这种情况下,即使没有引用 TEXT 列,也会增加聚集索引(叶节点)中每一行的大小。这减慢了 table 对其他非 TEXT 列的扫描速度,因为每页适合的页面较少(平均要扫描更多页面以找到您要查找的内容),但在扫描 TEXT 列(第一个768 字节)。您是否经常进行 table 扫描?希望您能够使用索引来避免 table 扫描。
索引是 b-trees 并且键搜索在内部节点完成,其中只包含键。对于聚簇索引,那只是主键,所以聚簇索引搜索不受叶节点中数据量的影响(但受主键大小影响)。
对于 InnoDB 的 Barracuda 文件系统,整个 TEXT 列存储在溢出页中(可以压缩)。它的任何部分都不存储在聚集索引(叶节点)中。因此,如果您使用的是 Barracuda 文件系统,让 MySQL 为您进行分离,并将 TEXT 列放在相同的 table 中。在这种情况下,您没有任何收获,因为 MYSQL 已经将 TEXT 列放在其他地方并且不会影响扫描非 TEXT 列。
如果您正在使用 Antelope,如果您经常扫描非 TEXT 列(无论如何都应该避免),并且您很少引用 TEXT 列,则可以考虑拆分它。将其拆分为两个 tables,要读取整个记录,您现在必须在两个聚簇索引上进行搜索,这是一个的两倍。
我还可以看到想要在 MySQL 的 InnoDB 缓冲区 space 的 RAM 有限的系统上将其与 Antelope 拆分,并且您很少引用 TEXT 列。包含非 TEXT 列的叶节点如果较小,则更有可能保留在内存中。