MySql Tinytext vs Varchar vs Char

Posted

技术标签:

【中文标题】MySql Tinytext vs Varchar vs Char【英文标题】: 【发布时间】:2011-11-09 20:10:33 【问题描述】:

构建一个有可能受到点击量和流量重创的系统。 这是一个典型的 Apache/php/mysql 设置。

之前已经构建了很多系统,但从来没有遇到过我必须就这种规模的潜在可扩展性做出决定的情况。我有很多关于构建这种规模的系统的问题,但对于这个特定的问题,我正在尝试决定使用什么作为数据类型。

这是 100 英尺的视图:

我们有一个表(除其他外)有一个 description 字段。我们已决定将其限制为 255 个字符。它将是可搜索的即:显示所有描述包含...的条目)。问题:此表可能在某个时候有数以百万计的条目我们认为)。

我还没有想出搜索的策略(MySql LIKE 运算符可能很慢和/或我猜这么大的 # 记录是个猪),但那是另一个 SO 问题。对于这个问题,我想知道将此字段创建为 tinytext、varchar 和 char 的利弊是什么

不是数据库专家,所以任何和所有评论都是有帮助的。谢谢-

【问题讨论】:

由于看起来问题已被编辑为明确包含搜索文本字段的问题,您可能需要编辑标题以澄清这一点。 @tehshrike:我没有编辑它。我的问题仍然是一样的(每个的优点和缺点)。看起来每个人都跳上了“搜索”部分。显然,很多人对每种数据字段之间的差异感兴趣。根据我阅读的所有内容,听起来像是对搜索的洗礼(只需使用您想要的任何内容,然后在需要时使用索引软件组件)。不过,仍在等待有人分析每种方法的优缺点。 【参考方案1】:

使用CHAR

BLOB's 和TEXT's 存储在行外,因此读取它们会受到访问惩罚。 VARCHAR 是可变长度的,这样可以节省存储空间,因为可能会引入小的访问损失(因为行并非都是固定长度的)。

但是,如果您正确创建索引,VARCHARCHAR 可以完全存储在索引中,这将使访问速度更快。

见:varchar(255) v tinyblob v tinytext 并且:http://213.136.52.31/mysql/540 并且:http://forums.mysql.com/read.php?10,254231,254231#msg-254231 还有:http://forums.mysql.com/read.php?20,223006,223683#msg-223683

顺便说一句,根据我的经验,对于简单查询(即SELECT ID WHERE SOME_COLUMN REGEX 'search.*'),MySQL regex 运算符比 LIKE 快得多,而且显然更通用。

【讨论】:

谢谢。现在正在研究4篇文章。投票赞成。不过还不确定要接受哪个答案——还有很多需要挖掘。 那里有一些很好的信息,但没有一个与您的问题完全相关 - 它存储在哪里,或者它是否是固定宽度无关紧要 - 如果您有数百万行,您不能使用表扫描。您需要索引,并且任何文本字段上的普通索引都不允许您在字段中间搜索文本。 @tehshrike:嗯,我的问题不是关于搜索,而是关于每种数据类型的优缺点。就像我在问题中提到的那样,“搜索”部分将是一个单独的问题。我实际上认为他提供的信息很好。 @OneNerd “但那是另一个 SO 问题” - 你做到了!我的错。这是一个很大的问题,这就是重点。我强烈推荐看看这本书:mo4.us/IjO @Seth:是的,只要搜索字段的开头,就可以使用索引。但这不是 OneNerd 所说的他会做的事情:“向我展示所有描述包含...的条目”【参考方案2】:

我相信使用 varchar,您可以在低级别存储在实际数据库中的可变长度,这意味着它可以占用更少的磁盘空间,即使一行不使用所有的文本字段,它的固定长度也是如此它。固定长度的字符串查询起来应该更快。

编辑:我刚刚查了一下,文本类型也存储为可变长度。最好的办法是用 mysqlslap 之类的东西对其进行基准测试

关于您的其他未提出的问题,您可能希望构建某种搜索索引,将描述字段中的每个有用词单独与描述联系起来,然后您可以对其进行索引并进行搜索.将比使用 %like% 快得多。

【讨论】:

我正在查看 forums.mysql.com/read.php?24,105964,105964 和 forums.mysql.com/read.php?10,254231,254581#msg-254581 - 由于各种原因,似乎 varchar 是最多 255 个字符的赢家。 很好,看起来基准测试已经完成,所以你去吧。 谢谢。现在正在研究这些文章。投票赞成。不过还不确定要接受哪个答案——还有很多需要挖掘。【参考方案3】:

在您的情况下,如果您使用LIKE,则所有三种类型都不好(LIKE '%string%' 不会使用在该列上创建的任何索引,无论其类型如何)。其他一切都只是噪音。

我不知道 TINYTEXTVARCHAR 最多 255 个字符之间有什么重大区别,而 CHAR 只是不适用于可变长度字符串。

所以我的建议:选择 VARCHARTINYTEXT(我个人会选择 VARCHAR)并使用全文搜索引擎(如 Lucene、Sphinx 或任何其他为您完成工作的其他引擎)索引该列的内容.忘记LIKE(即使这意味着您需要自己定制构建全文搜索索引引擎,无论出于何种原因,即您需要支持一组没有任何引擎可以满足的功能)。

【讨论】:

确实,如果您查看表扫描,所有这些都同样糟糕。旧的 MyISAM 引擎确实支持全文索引,但根据我的经验,它不是一个非常有用的实现。 我没有想过要使用 MyISAM 支持的那个(也不喜欢这样的原始引擎)。我正在考虑诸如 Lucene 或 Sphinx 之类的东西,或者如果有意义的话,真的要制作一个自定义的全文索引。的确,我的回答令人困惑,但我更新了它以解决这个问题。【参考方案4】:

如果您想在数百万行中搜索,请将所有这些文本存储在不同的表中(这将减少大表的行大小),如果您的文本数据很短,请使用 VARCHAR,如果您需要更多,请使用 TEXT长度。

不要使用LIKE 进行搜索,而是使用专门的解决方案,例如 Lucene、Sphinx 或 Solr。我不记得是哪一个,但其中至少一个可以轻松配置为实时或接近实时的索引。

编辑

我提出的将文本存储在不同表中的建议减少了主表所需的 IO,但是当插入数据时,它需要保留一个额外的索引并在选择中增加连接开销,因此只有在使用表读取一些数据时才有效描述一次,表中的其他数据被更频繁地使用。

【讨论】:

单列最多255(意思是:可能大部分时间大约是100个字符或更短)应该不是问题,所以我认为它没有意义将此列存储在外部表中。 取决于您的数据大小 - 如果您的连续数据较少,您可以更快地从磁盘读取它并更有效地使用缓存。 100 万行中减少 100 字节在表扫描期间减少读取 100 MB = 表中减少约 6400 页(假设标准 InnoDB 每页 16 KB)。这是一种廉价的优化,可能会在未来得到回报。 那么让我们为每个超过 50 字节的varchar 列构建一个表?我看到的问题是:在性能危急的情况下,你为什么要接受全表扫描却什么也不做?我不努力使全表扫描更快,我努力不陷入需要全表扫描的情况。显然,这并非在任何时候都是可能的,但在重要的地方,这在我的书中是必须的。 表扫描它不是要走的路。 我仅使用表扫描作为示例,在其中我可以轻松计算优势。 @Mariusz - 不是每个varchar,但如果表要包含数百万个条目,那么可以轻松地将描述之类的内容存储在其他地方,从而减少行大小,例如。 50%(并允许每个磁盘页有更多行)

以上是关于MySql Tinytext vs Varchar vs Char的主要内容,如果未能解决你的问题,请参考以下文章

MySQL 中的 VARCHAR(255) 和 TINYTEXT 字符串类型有啥区别?

MySQL:我是使用 TINYTEXT 还是 VARCHAR(6) 来表示简短的单词

有任何理由使用 TINYTEXT 吗?

mysql数据类型以及各种语句的总结

Mysql简单介绍

MySQL数据类型