【问题标题】:Handling a huge MYSQL Table处理一个巨大的 MYSQL 表
【发布时间】:2011-09-20 06:10:34
【问题描述】:

希望你们都做得很好。我们有一个名为“posts”的巨大 mysql 表。它有大约 70,000 条记录,并且已达到大约 10GB 的大小。

我的老板说必须做一些事情来让我们更容易处理这个巨大的表,因为如果那个表被损坏了,那么我们需要很多时间来恢复这个表。有时它也很慢。

有哪些可能的解决方案,以便在各个方面都更容易处理此表。

表结构如下:

CREATE TABLE IF NOT EXISTS `posts` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `thread_id` int(11) unsigned NOT NULL,
  `content` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  `first_post` mediumtext CHARACTER SET utf8 COLLATE utf8_unicode_ci,
  `publish` tinyint(1) NOT NULL,
  `deleted` tinyint(1) NOT NULL,
  `movedToWordPress` tinyint(1) NOT NULL,
  `image_src` varchar(500) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
  `video_src` varchar(500) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
  `video_image_src` varchar(500) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
  `thread_title` text CHARACTER SET utf8 COLLATE utf8_unicode_ci,
  `section_title` text CHARACTER SET utf8 COLLATE utf8_unicode_ci,
  `urlToPost` varchar(280) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
  `posts` int(11) DEFAULT NULL,
  `views` int(11) DEFAULT NULL,
  `forum_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
  `subject` varchar(150) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
  `visited` int(11) DEFAULT '0',
  `replicated` tinyint(4) DEFAULT '0',
  `createdOn` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `urlToPost` (`urlToPost`,`forum_name`),
  KEY `thread_id` (`thread_id`),
  KEY `publish` (`publish`),
  KEY `createdOn` (`createdOn`),
  KEY `movedToWordPress` (`movedToWordPress`),
  KEY `deleted` (`deleted`),
  KEY `forum_name` (`forum_name`),
  KEY `subject` (`subject`),
  FULLTEXT KEY `first_post` (`first_post`,`thread_title`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=78773 ;

谢谢你。

更新

注意:虽然我对这些回复非常满意,但几乎所有的答案都是关于优化当前数据库,而不是关于如何处理大表。虽然我可以根据收到的回复优化数据库,但它确实不能回答关于处理大型数据库的问题。现在我说的是 70,000 条记录,但在接下来的几个月(如果不是几周)内,我们将增长一个数量级。每条记录的大小约为 300kb。

【问题讨论】:

  • 你为什么首先使用 MyISAM?如果唯一的原因是全文索引,请考虑迁移到 InnoDB 并在 mysql(lucene/solr、sphinx)外部或自己处理全文。
  • @Darhazer - 感谢您的评论,尽管迁移到 InnoDB 的优势是什么。我并没有真正意识到这一点。 MyISAM 的缺点是什么?为什么要在mysql之外处理全文?
  • @Darhazer - 请查看我的问题中的更新部分
  • @Imran:70K 行并不是一张大表。有人会说它很小。一排有 300KB 闻起来很糟糕的数据库设计。我也很想看看其他桌子的设计。
  • MyISAM 使用表级锁,而 InnoDB 使用行级锁。如果有很多插入/更新,这会对性能产生巨大影响。此外,MyISAM 将在写入密集型应用程序中完全崩溃(它针对读取进行了优化)。我们正在使用 InnoDB 在 MySQL 中处理数百万条记录、数十 GB 表。 InnoDB 有许多 MyISAM 不支持的特性,比如事务。缺点是不支持全文索引。但是,将搜索移到数据库之外可以将数据库服务器从该操作中解放出来,这是一个通用的性能提示。

标签: mysql database scaling


【解决方案1】:

我猜你必须更改一些列。

您可以从减少 var char 变量开始。

image_src/video_src/video_image_src VARCHAR(500) 我觉得有点太多了。 (我想说 100 个 varchars 就足够了)

thread_title 是文本,但如果你说我应该是 VARCHAR(200?) 与 section_title 相同

好的,这是你的问题 content长文

这里真的需要长文本吗? longtext 最多 4GB 的空间。我认为如果您将此列更改为文本,它会小很多

    TINYTEXT    256 bytes    
    TEXT    65,535 bytes    ~64kb
    MEDIUMTEXT   16,777,215 bytes   ~16MB
    LONGTEXT    4,294,967,295 bytes ~4GB

编辑:我看到你使用全文索引。我很确定这会节省很多很多数据。您应该使用另一种机制来搜索全文。

【讨论】:

  • 另外,他的一些 int(11) 可以减少,比如 Views, Posts, Visited... 即使在 S/O 上,你见过多少帖子超过 99,999意见更不用说针对问题的帖子...
  • varchars 不会占用所有 500 字节的内存,只是存储的内容 + 一些额外的字节。我相信文本字段也是如此(尽管使用较大的字段类型存在一些内存问题,例如在准备好的语句中)。然而,MyISAM 使用固定宽度的列更快。至于 redusing int 让我们说短整数 - 我同意
  • @Darhazer。你是对的,它不需要额外的高清空间。但它确实需要额外的 RAM 内存。所以总是越少越好。来源:dev.mysql.com/doc/refman/5.0/en/char.html
【解决方案2】:

我的回答也是对前两个 cmets 的补充。

您已索引了一半的表格。但是,如果您查看一些索引(publish、deleted、movedToWordPress),您会注意到它们是 1 或 0,因此它们的选择性很低(行数除以该列的不同值数)。这些索引是浪费空间。

有些事情也没有意义。 tinyint(4) - 实际上并没有使它成为一个 4 位整数。数字有显示长度。 tinyint 是 1 个字节,所以它有 256 个可能的值。我假设那里出了点问题。

另外,只有 75k 条记录需要 10 个演出?你是怎么测量尺寸的?另外,你的硬件是什么?

编辑关于您更新的问题:

有很多方法可以扩展数据库。我将链接一个 SO 问题/答案,以便您了解您可以做什么:here it is。 您可能会做的另一件事是获得更好的硬件。通常,数据库在大小增加时变慢的原因是 HDD 子系统和用于处理数据集的可用内存。您拥有的 RAM 越多 - 速度就越快。

您可以做的另一件事是将您的表格分成两个表格,其中一个表格保存文本数据,另一个表格保存与您的系统执行某些搜索或匹配所需的数据相关的数据(您可以放置​​整数字段那里)。 使用 InnoDB,如果两个表通过某种指向主键的外键连接,您将获得巨大的性能提升。由于 InnoDB 的主键查找速度很快 - 您正在为您可以对数据集执行的操作提供几种新的可能性。如果您的数据变得越来越大,您可以获得足够的 RAM,InnoDB 将尝试在 RAM 中缓冲数据集。有一个有趣的东西叫做 HandlerSocket,它对有足够 RAM 并使用 InnoDB 的服务器有一些巧妙的作用。

最终归结为您需要做什么以及如何做。由于您没有提到这一点,因此很难在此估计您应该做什么。 我优化的第一步肯定是调整 MySQL 实例并备份那个大表。

【讨论】:

  • 数据库文件在lamp上可用。我可以直接访问它们。这就是我检查文件大小的方式。我只使用普通的 HP Pavilion dm4、i7 2.33mghz 运行 UBuntu、4GB RAM
  • 你调整 MySQL 设置了吗?
  • @Michael J.V. - 请查看我的问题中的更新部分
  • @Michael:+1。我会考虑将表拆分为 2 个以上的表 - 您的建议加上 MyISAM 中的一个表,以免丢失全文搜索。甚至将每个位字段(错误地实现为 tinyint)拆分到单独的表中,以避免其中出现任何 NULL。所有这些都可以在 InnoDB 引擎中更好地工作。
【解决方案3】:

除了 Michael 所评论的之外,速度慢可能是一个问题,具体取决于查询的优化程度以及要匹配的正确索引。我会尝试找出一些花费比您希望的时间更长的罪魁祸首查询,并在 S/O 上发布,看看是否有人可以帮助优化选项。

【讨论】:

    猜你喜欢
    • 2010-10-31
    • 2018-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-14
    • 1970-01-01
    • 2012-01-20
    • 1970-01-01
    相关资源
    最近更新 更多