希望你们都做得很好。我们有一个巨大的mysql表叫做'posts'。它有大约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。
答案 0 :(得分:6)
我的回答也是前两条评论的补充。
你已经将你桌子的一半编入索引。但是如果你看一些索引(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实例并支持那个大表。
答案 1 :(得分:2)
我想你必须改变一些列。
您可以从减少var char变量开始。
image_src / video_src / video_image_src我认为VARCHAR(500)有点太多了。 (100个变种就足够了)
thread_title是文本但如果你说我应该是VARCHAR(200?) 与section_title相同
好的,这是你的问题
content
longtext
你真的需要龙骨文吗? longtext是高达4GB的空间。我想如果你把这个专栏改成文字,那就会小很多
TINYTEXT 256 bytes
TEXT 65,535 bytes ~64kb
MEDIUMTEXT 16,777,215 bytes ~16MB
LONGTEXT 4,294,967,295 bytes ~4GB
编辑:我看到你使用全文索引。我很确定这会节省很多很多数据。您应该使用其他机制来搜索全文。
答案 2 :(得分:0)
除了Michael所评论的内容之外,根据查询的优化程度和匹配的正确索引,缓慢可能是一个问题。我会尝试找到一些比你希望花费更长时间的罪魁祸首查询,并在S / O发布,看看是否有人可以帮助优化选项。