要求:
第1页 - >显示最近10篇博文的用户和1-2行预览
第2页 - >显示带有全文的单个博文.
MySQL table -> userid -> varchar 50
post_id -> integer
post_title -> varchar 100
post_description -> varchar 10000
Run Code Online (Sandbox Code Playgroud)
对于第1页,从blog_table中选择user_id,post_title,post_description.post_description的子字符串用于在列表中显示预览.
对于第2页,选择user_id,post_title,post_description,其中post_id = N.
MySQL table -> userid -> varchar 50
post_id -> integer
post_title -> varchar 100
post_brief -> varchar 250
post_description -> text
Run Code Online (Sandbox Code Playgroud)
对于第1页,从blog_table中选择user_id,post_title,post_brief.
对于第2页,选择user_id,post_title,post_description,其中post_id = N.
是否存储两列,一个简短的varchar和一个full作为文本(因为它访问文件系统,并且只在需要时才应该查询),是否值得获得性能优势?
因为,方法2将仅存储指向行中文本的指针,而方法1将在行中存储完整的varchar 10K字符串.它是否会影响可驻留在RAM中的表数据量,从而影响查询的读取性能?
Haz*_*zit 16
SQL查询的性能主要取决于JOIN,WHERE子句,GROUP BY和ORDER BY,而不取决于检索的列.如果检索到的数据要多得多,可能必须通过网络进行编程语言处理,那么这些列只会对查询的速度产生明显影响.这里情况不同.
简短回答:两个建议设置之间的性能差异可能非常小.
为了获得良好的速度,您的post_id列应具有(唯一)索引.您不是通过任何其他列进行选择,排序或分组,因此数据可以直接来自表,这是一个非常快速的过程.
你在这里谈论"页面",所以我猜这些会被呈现给用户 - 你似乎不太可能想要在同一页面上向人类显示数千个博客帖子,因此你可能会这样做实际上你的陈述中有ORDER BY和/或LIMIT条款,你没有在你的问题中包含这些条款.
但让我们深入了解整个事情.假设我们实际上是直接从硬盘读取大量的TEXT列,难道我们不会达到驱动器的最大读取速度吗?不会只检索VARCHAR(250)更快,特别是因为它可以节省额外的LEFT()调用吗?
我们可以快速地从桌面上获得LEFT()调用.字符串函数非常快 - 毕竟,CPU只是切断了一些数据,这是一个非常快速的过程.它们产生明显延迟的唯一时间是在WHERE子句,JOIN等中使用它们,但这不是因为这些函数很慢,而是因为它们必须运行很多次(可能是数百万次)才能甚至产生一行结果,甚至更多,因为这些使用通常会阻止数据库正确使用其索引.
所以最后归结为:MySQL从数据库中读取表内容的速度有多快.而这又取决于您使用的存储引擎及其设置.MySQL可以使用许多存储引擎,包括(但不限于)InnoDB和MyISAM.这两个引擎都为大型对象(如TEXT或BLOB列)提供了不同的文件布局(但有趣的是,还有VARCHAR).如果TEXT列存储在与行的其余部分不同的页面中,则存储引擎必须为每行检索两个页面.如果它与其余部分一起存储,它将只是一页.对于顺序处理,这可能是性能的重大变化.
这里有一些背景阅读:
答案很长:取决于:)
您必须在自己的硬件上进行一些基准测试才能实际调用哪个布局实际上更快.鉴于第二个设置通过其附加列引入冗余,在大多数情况下可能会表现更差.如果 - 并且仅当 - 表结构允许较短的VARCHAR列适合磁盘上的同一页面而较长的TEXT列位于另一页面上时,它将表现得更好.
编辑:有关TEXT列和性能的更多信息
似乎存在关于BLOB和内存处理的常见误解.相当多的页面(包括StackOverflow上的一些答案 - 我将尝试找到它们,并给出一个额外的注释)声明TEXT列(以及所有其他BLOB)不能由MySQL在内存中处理,因此总是如此表现猪.事实并非如此.真正发生的是这个:
如果您运行涉及TEXT列的查询并且该查询需要处理临时表,则 MySQL必须在磁盘上而不是在内存中创建该临时表,因为MySQL的MEMORY存储引擎无法处理TEXT列.看到这个相关的问题.
在MySQL文档状态本(段落是所有版本从3.2至5.6相同):
使用临时表处理的查询结果中的BLOB或TEXT列的实例会导致服务器在磁盘而不是内存中使用表,因为MEMORY存储引擎不支持这些数据类型(请参阅第8.4.3.3节, "MySQL如何使用内部临时表".使用磁盘会导致性能下降,因此只有在确实需要时才在查询结果中包含BLOB或TEXT列.例如,避免使用选择所有列的SELECT*.
这是让人困惑的最后一句话 - 因为这只是一个不好的例子.一个简单的SELECT *将不会通过这种性能问题的影响,因为它不会使用临时表.如果同样选择了例如由非索引列排序,它会不得不使用临时表,会影响此问题.使用EXPLAINMySQL中的命令查明查询是否需要临时表.
顺便说一下:这些都不会影响缓存.TEXT列可以像其他任何内容一样进行缓存.即使查询需要临时表并且必须存储在磁盘上,如果系统有资源执行此操作,结果仍然可以缓存,并且缓存不会失效.在这方面,TEXT列就像其他任何东西一样.
编辑2:有关TEXT列和内存要求的更多信息......
MySQL使用存储引擎从磁盘中检索记录.然后它将缓冲结果并按顺序将它们交给客户端.以下假设此缓冲区最终在内存中而不在磁盘上(参见上文原因)
对于TEXT列(和其他BLOB),MySQL将缓冲指向实际BLOB的指针.这样的指针仅使用存储器的几个字节,但需要从磁盘检索时的行被切换到客户机的实际文本内容.对于VARCHAR列(以及除BLOB之外的所有其他列),MySQL将缓冲实际数据.这通常会占用更多内存,因为大多数文本都不仅仅是几个字节.对于计算列,MySQL也会缓冲实际数据,就像使用VARCHAR一样.
关于这一点的几点注意事项:从技术上讲,BLOB在被移交给客户端时也会被缓冲,但是一次只能传输一个 - 而且大型BLOB可能不是完整的.由于此缓冲区在每行之后被释放,因此不会产生任何重大影响.此外,如果BLOB实际存储在与该行的其余部分相同的页面中,则它最终可能会被视为VARCHAR.说实话,我从来没有要求在一个查询中返回大量的BLOB,所以我从未尝试过.
现在让我们回答(现在编辑过的)问题:
第1页.用户概述和短博客文章片段.
您的选择几乎就是这些查询
SELECT userid, post_title, LEFT(post_description, 250) FROM `table_method_1` <-- calculated based on a VARCHAR column
SELECT userid, post_title, LEFT(post_description, 250) FROM `table_method_2` <-- calculated based on the TEXT column
SELECT userid, post_title, post_brief FROM `table_method_2` <-- precalculated VARCHAR column
SELECT userid, post_title, post_description FROM `table_method_2` <-- return the full text, let the client produce the snippet
Run Code Online (Sandbox Code Playgroud)
前三个的内存要求是相同的.第四个查询将需要更少的内存(TEXT列将作为指针缓冲),但更多的流量到客户端.由于流量通常通过网络(在性能方面很昂贵),这往往比其他查询慢 - 但您的里程可能会有所不同.通过告诉存储引擎使用内联表格布局,可以加快TEXT列上的LEFT()函数,但这取决于存储的文本的平均长度.
第2页.一篇博文
SELECT userid, post_title, post_description FROM `table_method_1` WHERE post_id=... <-- returns a VARCHAR
SELECT userid, post_title, post_description FROM `table_method_2` WHERE post_id=... <-- returns a TEXT
Run Code Online (Sandbox Code Playgroud)
内存要求很低,因为只缓冲一行.由于上述原因,第二个将需要一点点内存来缓冲行,但需要一些额外的内存来缓冲单个BLOB.
在任何一种情况下,我都非常确定你不关心选择的内存要求只会返回一行,所以它并不重要.
摘要
如果您有任意长度的文本(或任何需要超过几千字节的文本),您应该使用TEXT列.这就是他们的目的.MySQL处理这些列的方式在大多数情况下都是有益的.
日常使用中只记住两件事:
EXPLAIN有疑问时请使用语法.当你坚持这些规则时,你应该从MySQL获得相当不错的性能.如果您需要进一步优化,那么您将需要查看更精细的细节.这将包括存储引擎和相应的表格布局,有关实际数据的统计信息以及有关所涉及硬件的知识.根据我的经验,我通常可以摆脱性能猪而不必深入挖掘.