MySQL中的解耦表能提高多少性能?

时间:2015-04-21 03:20:43

标签: mysql database performance database-design database-performance

我正在设计数据库以在MySQL中存储一些博客文章。我最近碰到了这个answer,建议你什么时候:

  1. 将定期查询的表格(例如博客文章列表),但
  2. 该表中的一列包含大量无法定期访问的数据(博客内容)
  3. 如果将内容存储在单独的表中,那么性能会更好,因此当您生成列表时,它会更快。

    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
    

    它在多大程度上成为性能问题? (几百,几万??百万?)

2 个答案:

答案 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)才能扩展。但这与垂直分区无关。