我正在设计数据库以在MySQL中存储一些博客文章。我最近碰到了这个answer,建议你什么时候:
如果将内容存储在单独的表中,那么性能会更好,因此当您生成列表时,它会更快。
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
它在多大程度上成为性能问题? (几百,几万??百万?)
答案 0 :(得分:7)
使用MySQL 5.5及更高版本,InnoDB存储引擎支持Barracuda file format。为了使用InnoDB的Barracuda文件格式,您必须使用每表文件表空间,或使用通用表空间(单文件“系统”InnoDB表空间不支持Barracuda)。
在Barracuda(Antelope)之前,MySQL always stored at least the first 768 bytes of a TEXT column in the clustered (primary key) index。在这种情况下,具有TEXT列,即使没有引用它,也会增加聚簇索引(叶节点)中每行的大小。由于较少的页面适合每个页面(平均扫描更多页面以查找您正在查找的内容),因此在其他非TEXT列上的表扫描速度变慢,但在扫描TEXT列时仍然提高了性能(无论如何,前768个字节) 。你在做很多桌面扫描吗?希望您能够使用索引来避免表扫描。
索引为b-trees,密钥搜索在内部节点完成,内部节点仅包含密钥。对于聚簇索引,这只是主键,因此聚簇索引搜索不受叶节点中数据量的影响(但受主键大小影响)。
使用InnoDB的Barracuda文件系统,整个TEXT列存储在溢出页面中(可以压缩)。它的任何部分都不存储在聚簇索引(叶节点)中。因此,如果您正在使用Barracuda文件系统,请让MySQL为您进行分离,并将TEXT列放在同一个表中。在这种情况下你没有获得任何东西,因为MYSQL已经将TEXT列放在其他地方并且不影响扫描非TEXT列。
如果您正在使用Antelope,如果您经常扫描非TEXT列(无论如何应该避免),您可能会考虑拆分它,并且您很少引用TEXT列。将它拆分为两个表来读取整个记录,您现在必须对两个聚簇索引进行搜索,这两个索引的价格是一个索引的两倍。
我还可以看到想要在一个系统上将它与Antelope分开,在这个系统上,MySQL的InnoDB缓冲区空间有限,而你很少引用TEXT列。包含非TEXT列的叶节点如果较小则更有可能留在内存中。
答案 1 :(得分:0)
对你的所有问题都是。
当不总是需要TEXT
(或BLOB
等)时,“垂直分区”(构建“并行表”)非常有用。
当您不需要TEXT
时,由于该表中的批量较少,因此效果会更好。
如果确实需要TEXT
,则可能只提取一行(或极少数)行,因此JOIN
进入额外表的成本并不明显。
我有两个数据库,每个数据库有200K行,像这样分开。两者都缩放得很好。我希望数百万甚至数十亿都不成问题。 (好吧,“数十亿”有很多问题,但垂直分区是其中一个解决方案。)
您的示例SELECT
需要'复合'`INDEX(author_id,created)才能扩展。但这与垂直分区无关。