MySQL 5.5:对于 innodb 中的 text/varchar 字段,以下哪一项是更好的存储方式?

2023-12-30

要求 :

Page#1 -> 显示用户及其最新 10 篇博客文章的 1-2 行预览

Page#2 -> 显示带有全文的单个博客文章。

方法一:

MySQL table ->   userid -> varchar 50
                 post_id -> integer
                 post_title -> varchar 100
                 post_description -> varchar 10000

第 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

第 1 页,从 blog_table 中选择 user_id、post_title 、 post_brief 。

第 2 页,选择 user_id 、 post_title 、 post_description ,其中 post_id = N

存储两列,一列作为 varchar 存储,一列作为文本存储(因为它访问文件系统,并且应该仅在需要时查询),是否值得获得性能优势?

因为方法 2 将仅存储指向行中文本的指针,而方法 1 将在行中存储完整的 varchar 10K 字符串。它是否会影响可驻留在 RAM 中的表数据量,从而影响查询的读取性能?


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 列存储在与行的其余部分不同的页中,则存储引擎必须为每行检索两个页。如果它与其他内容一起存储,那么它就只是一页。对于顺序处理来说,这可能是性能的重大变化。

以下是一些相关背景阅读:

  • InnoDB 中的 Blob 存储 http://www.mysqlperformanceblog.com/2010/02/09/blob-storage-in-innodb/
  • MyISAM 动态与压缩数据文件布局 http://dev.mysql.com/doc/internals/en/myisam.html

长答案:这取决于:)

您必须在自己的硬件上进行大量基准测试,才能真正确定哪种布局实际上更快。鉴于第二种设置通过附加列引入了冗余,因此在大多数情况下它的性能可能会更差。当且仅当表结构允许较短的 VARCHAR 列适合磁盘上的同一页,而长的 TEXT 列位于另一页上时,它的性能会更好。

编辑:有关 TEXT 列和性能的更多信息

关于 BLOB 和内存中处理似乎存在一个常见的误解。相当多的页面(包括 StackOverflow 上的一些答案 - 我将尝试找到它们,并给出附加评论)指出 TEXT 列(以及所有其他 BLOB)无法由 MySQL 在内存中处理,因此总是性能猪。那不是真的。真正发生的事情是这样的:

如果您运行涉及 TEXT 列的查询and该查询需要一个临时表来处理,thenMySQL 必须在磁盘上而不是在内存中创建临时表,因为 MySQL 的MEMORY存储引擎无法处理 TEXT 列。看这个相关问题 https://stackoverflow.com/questions/2883867/mysql-text-field-performance.

The MySQL 文档 http://dev.mysql.com/doc/refman/5.5/en/blob.html声明如下(该段落对于 3.2 到 5.6 的所有版本都是相同的):

查询结果中 BLOB 或 TEXT 列的实例 使用临时表进行处理会导致服务器使用以下表: 磁盘而不是内存中,因为 MEMORY 存储引擎不 支持这些数据类型(请参见第 8.4.3.3 节,“MySQL 如何使用 内部临时表”)。使用磁盘会导致性能损失, 因此,仅在查询结果中包含 BLOB 或 TEXT 列 真的需要。例如,避免使用 SELECT *,它会选择所有 列。

最后一句话让人困惑——因为那只是一个坏例子。一个简单的SELECT * will not受到此性能问题的影响,因为不会使用临时表。例如,如果相同的选择按非索引列排序,则它would必须使用临时表并且会受到影响通过这个问题。使用EXPLAINMySQL 中的命令可查明查询是否需要临时表。

顺便说一句:这些都不会影响缓存。 TEXT 列可以像其他任何列一样被缓存。即使查询需要临时表并且必须存储在磁盘上,如果系统有足够的资源,结果仍然可以被缓存,并且缓存不会失效。在这方面,TEXT 列就像其他任何列一样。

编辑 2:有关 TEXT 列和内存要求的更多信息...

MySQL 使用存储引擎从磁盘检索记录。然后它将缓冲结果并按顺序将它们传递给客户端。以下假设该缓冲区最终位于内存中而不是磁盘上(请参阅上面的原因)

对于 TEXT 列(和其他 BLOB),MySQL 将缓冲指向实际 BLOB 的指针。这样的指针仅使用几个字节的内存,但需要在将行传递给客户端时从磁盘检索实际的 TEXT 内容。 对于 VARCHAR 列(以及除 BLOB 之外的所有其他列),MySQL 将缓冲实际数据。这通常会使用更多内存,因为大多数文本都不仅仅是几个字节。 对于计算列,MySQL 还将缓冲实际数据,就像 VARCHAR 一样。

对此有几点说明:从技术上讲,BLOB 在移交给客户端时也会被缓冲,但一次只能缓冲一个 - 对于大型 BLOB 可能不会全部缓冲。由于该缓冲区在每行之后都会被释放,因此这不会产生任何重大影响。另外,如果 BLOB 实际上与行的其余部分存储在同一页中,则它最终可能会被视为 VARCHAR。说实话,我已经never有回国要求lots单个查询中的 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

前三个的内存要求是完全相同的。第四个查询将需要less内存(TEXT 列将作为指针进行缓冲)但是more到客户端的流量。由于流量通常通过网络进行(就性能而言昂贵),因此这往往比其他查询慢 - 但您的里程可能会有所不同。 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

一开始,内存要求就很低,因为只有一行会被缓冲。由于上述原因,第二个方法将需要少量的内存来缓冲行,但需要一些额外的内存来缓冲单个 BLOB。

在任何一种情况下,我很确定您不关心仅返回一行的选择的内存要求,因此这并不重要。

Summary

如果您有任意长度的文本(或任何需要超过几千字节的文本),则应使用 TEXT 列。这就是他们存在的目的。 MySQL 处理这些列的方式是有益的大多数时候.

日常使用时只需记住两件事:

  • 如果您实际上不需要它们,请避免选择 TEXT 列、BLOB 列以及可能包含大量数据的所有其他列(是的,其中包括 VARCHAR(10000))。当您只需要几个值时,“SELECT * FROM无论什么”的习惯会给数据库带来很多不必要的压力。
  • 当你are选择 TEXT 列或其他 BLOB,请确保选择不使用临时表。使用EXPLAIN语法有疑问时。

当您遵守这些规则时,您应该从 MySQL 获得相当不错的性能。如果您需要进一步优化,则必须查看更精细的细节。这将包括存储引擎和相应的表布局、实际数据的统计信息以及有关所涉及硬件的知识。根据我的经验,我通常可以摆脱性能消耗,而不必深入挖掘。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MySQL 5.5:对于 innodb 中的 text/varchar 字段,以下哪一项是更好的存储方式? 的相关文章

  • Mysqldb 属性错误:游标

    我开始在 python 中使用 mysqldb 模块 并且我似乎对调用查询的 标准 方式有一些问题 我知道标准方法是创建游标 然后用它来执行查询 然而 当我尝试实例化一个时 它给了我以下错误 属性错误 光标 我的数据库类如下所示 class
  • 如何在我的网站中创建全局搜索[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 如何在我的网站中创建全局搜索 该网站是内部网站 无法在网上使用 我无法使用 Google 搜索来实现此目的 我的信息全部存储在不同的
  • UUID 作为 MySQL id 列的默认值

    我正在尝试向 MySql 8 0 17 中的现有表添加一列 该列需要包含 UUID 我正在尝试将其设置为默认值 这是我正在执行的语句 ALTER TABLE myTable ADD COLUMN UUID varchar 36 NOT NU
  • 删除并加入同一个表

    是否可以执行连接同一个表的删除查询语句 我尝试过各种连接 内部 左侧 但没有运气 mysql 返回错误 我需要的例子 DELETE a FROM t1 AS a INNER JOIN t1 AS b USING some field b W
  • MySQL:如何检索随机行或多个随机行?

    我有一个 MySQL 数据库表 用于存储照片的 URL 我需要从特定类型的数据库中提取 5 条随机记录 我可以像这样提取 5 条记录 SELECT Photos FROM Photos WHERE Photos Type ID 4 LIMI
  • 如何选择非“唯一”行

    我有下表 我必须从中获取非唯一行 id idA infos 0 201 1899 1 205 1955 2 207 1955 3 201 1959 我想获取该列的所有行infos 具有相同的idA至少有两行的值 上表的查询输出必须是 inf
  • 在 PHP MySQL 中使用 jQuery AJAX 提交表单而无需重新加载

    我有一个基本的注册 登录页面 它使用 php 将数据提交到 SQL 数据库 但是 我希望页面在 jQuery AJAX 的帮助下不要在提交时重定向 无论成功与否 这是我目前所拥有的 但不起作用 它不显示任何错误消息 HTML 注册 html
  • 连接两个表并保存到第三个sql

    我想加入两张桌子 TableA wordA primarykey countA abc 25 abcd 29 abcde 45 TableB wordB primarykey countB ab
  • 使用java将数据插入mySQL表

    I have a predefined table in a mySQL database 我正在努力将从用户输入的数据保存到数据库中 但我似乎无法将任何数据保存在数据库中 使用以下代码 我尝试更新数据库的第一行 ID 1 到 OTHER
  • 使用一条语句在 MySQL 中添加多列

    我试图将多个列添加到 phpMyAdmin 中的现有表中 但我不断收到相同的错误 1064 你的 SQL 语法有错误 检查与您的 MySQL 服务器版本相对应的手册以获取正确的语法 我在写信 ALTER TABLE WeatherCente
  • 无法使用php连接到远程数据库

    我在 Windows 中安装了 Xampp 并且正在使用 Laravel 5 3 创建一个应用程序 我正在尝试在本地网络上的另一台服务器上执行查询 但是当我尝试这样做时 MySql 服务器使用以下命令对本地服务器上的用户进行身份验证 use
  • PHP、MySQL、PDO 事务 - fetchAll() 可以在 commit() 之前吗?

    更多交易问题 我现在拥有的是一堆串在一起的查询 如果有任何失败 都会手动反转 代码块1 stmt1 db gt prepare Update table1 set col col 1 if stmt1 db gt execute stmt2
  • 使用Python mysql.connector远程连接MySQL

    以下代码 在同一 LAN 内与 mysql 服务器不同的机器上运行 使用 Python3 和 mysql connector 本地连接到 MySQL 数据库 import mysql connector cnx mysql connecto
  • 计算链接上的点击次数(不带 onclick)[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我有诸如此类的链接 a href h
  • SQL Server 与 MySQL:CONTAINS(*,'FORMSOF(THESAURUS,word)')

    我很震惊 当我在 SQL Server 中看到查询非常简单时 我花了 3 4 天弄清楚如何在 mysql 中实现词干提取 和同义词搜索 Select from tab where CONTAINS FORMSOF THESAURUS wor
  • 使用 MySQL 5、简单成员资格提供程序、ASP.NET MVC4 和实体框架 5

    我在尝试着 使用 ASP NET MVC 4 对 MySQL 使用基于简单成员资格提供程序的身份验证默认 Web 应用程序配置为使用 MySQL 使用以下给出的教程 http www nsilverbullet net 2012 11 07
  • 根据另一个表中的值查找总计数

    在Mysql中 我的表中有具有重复值的城市 表城市 Name New York USA New York USA Chicago USA Chicago USA Chicago USA Paris France Nice France Mi
  • 如何在应用程序级别管理只读数据库连接

    我们使用的是Java Spring Ibatis MySql 有没有办法利用这些技术在应用程序级别管理只读连接 我希望在只读 MySql 用户的基础上添加额外的保护层 如果 BasicDataSource 或 SqlMapClientTem
  • MySQL 客户端和服务器无法通信,因为它们不具备通用算法

    我在 AWS 服务器上运行以下代码 尝试连接到 AWS 提供的 mysql 服务 String conn buildConnString dc MySqlConnection connection new MySqlConnection c
  • NodeJS:MySQL 有时会引发 ETIMEDOUT 错误

    我目前正在使用 NodeJS 开发一个应用程序 然而 经常服务器抛出这个错误 我无法与mysql交互 Error read ETIMEDOUT code ETIMEDOUT errno ETIMEDOUT syscall read fata

随机推荐

  • Google 地图 API v3 - 灰显或删除状态?

    是否可以将我不想从地图上看到的状态灰显 甚至更好地一起删除 搜索时无法找到任何明确的答案 我试图仅显示德克萨斯州地图并在其上放置标记 Thanks 你在寻找类似的东西吗这个 v2 示例 http maps forum nu gm texas
  • MSChart:饼图标签重叠问题

    我用过MSChart Control在我的一个VB NET项目 我决定将如下表所示的数据显示为饼图 但标签相互重叠 为了摆脱它 我已经尝试过 智能标签 属性如下图所示 Chart1 Series Default SmartLabelStyl
  • 如何防止标签栏控制器中的视图控制器旋转?

    我有一个管理 4 个选项卡的选项卡栏控制器 我对选项卡栏控制器进行了子类化 以便 shouldAutorotateToInterfaceOrientation 方法仅允许选项卡之一中的特定视图控制器旋转 一切工作几乎正常 其余选项卡中的控制
  • Oracle 数据库:DBMS_ALERT 在 Java 应用程序中的使用

    我有一个 java 应用程序服务器 使用 JDBC 与 oracle 11 2 数据库服务器进行通信 客户端的请求被发送到应用程序服务器 该应用程序服务器运行调用数据库中的第一个存储过程的java方法 我希望 java 方法在调用存储过程后
  • Python中线程之间的通信(不使用全局变量)

    假设我们有一个主线程 它为测试模块启动两个线程 test a 和 test b 无论测试模块执行完毕还是遇到任何错误 警告或者想要更新某些其他信息 两个测试模块线程都会保持其状态 主线程如何访问这些信息并采取相应的行动 例如 如果 test
  • 在R中获取Windows系统文件夹(用户主目录,“我的文档”等)路径

    我想获取用户主文件夹的完整路径 通常类似于 C Users USERNAME 或 我的文档 文件夹 但无法找到从 R 脚本执行此操作的方法 有什么解决办法吗 我想你想要 path expand
  • C# WPF 应用程序 .NET 4.5 设置鼠标位置 [重复]

    这个问题在这里已经有答案了 第一次在这里问问题 我在这里找到的解决方案似乎由于某种原因不起作用 我的应用程序需要在窗口激活时设置鼠标位置 我设置了该功能 但无法使光标属性发挥作用 由于某种原因 我无法使用 Cursor Position 或
  • 使用 SSH.NET 连接到 OpenSSH 7.4p1 失败,并显示“服务器响应在该位置包含空字符”,但在 WinSCP 中可以正常工作

    我正在尝试使用 SSH NET 2020 0 0 连接到 SFTP 服务器 我的代码看起来很简单 try var x new ConnectionInfo FtpIpAddress 22 FtpUser new PasswordAuthen
  • Scala 复制具有泛型类型的案例类

    我有两节课PixelObject ImageRefObject还有更多 但这里只是这两个类来简化事情 它们都是a的子类trait Object包含一个 uid 我需要通用方法 它将使用给定的新实例复制案例类实例uid 我需要它的原因是因为我
  • 使用 DotNetNuke 设置单独的 ASP.NET 应用程序

    我在 Windows Server 2008 64 位系统上安装了 DotNetNuke v5 1 4 社区版 使用 SQL Server 2008 64 位作为后端数据库 并且我想从中引用一个单独的 ASP NET 应用程序 我计划通过
  • 使用 Gremlin 在二部图上随机游走

    我想根据给定的用户偏好 用户喜欢的项目 基于使用groovy中的gremlin在有向二分图上进行随机游走来对项目进行排名 该图具有以下基本结构 用户1 喜欢 gt 项目A 项目B 此后我提出的查询 def runRankQuery def
  • 如何在Python中获取处理器名称?

    在我的 Windows 笔记本电脑上使用 Python 中的平台模块 我得到以下输出 import platform platform processor Intel64 Family 6 Model 58 Stepping 9 Genui
  • NSTextField 的边距和填充? (迅速)

    我想知道是否可以设置边距或填充NSTextField 我实现了或多或少自定义的文本字段 此屏幕截图中的第一个 使用此代码 myTextField wantsLayer true myTextField layer cornerRadius
  • Django 的 Db2 驱动程序?

    在我看来 Django 目前只提供了 4 个后端数据库引擎 它们是 django db backends postgresql django db backends mysql django db backends sqlite3 djan
  • 更改字典中键的名称

    如何更改 Python 字典中条目的键 只需 2 步即可轻松完成 dictionary new key dictionary old key del dictionary old key 或者一步 dictionary new key di
  • 我可以始终使用 WorkManager 而不是协程吗?

    我想知道既然有像 WorkManager 这样出色的解决方案 我为什么还要为 rx 或协程烦恼呢 但几乎所有教程都使用协程 那么 WorkManager 可能有缺点吗 两者的范围不同 WorkManager 可以推迟 任何以后的时间 或立即
  • Box2dweb - 碰撞接触点

    我使用box2dweb 我正在尝试开发一款游戏 在某些时候 我需要找出 圆 和 盒子 之间的接触点 我所知道的是可以使用 b2ContactListener 来完成 我们可以通过使用 Post Solve Event 实现 b2Contac
  • 如何反转 dplyr::select 的辅助函数?

    如何反转辅助函数dplyr select like matches or contains 以便我可以选择不包含或不匹配特定字符串的变量 例如 假设我想选择 mtcars 数据框中没有字母 m 的所有列 我可以想象做类似的事情 mtcars
  • Java 8 DateTimeFormatter 解析可选部分

    我需要将日期时间解析为两种不同格式的字符串 19861221235959Z 1986 12 21T23 59 59Z 以下 dateTimeFormatter 模式正确解析第一种日期字符串 DateTimeFormatter ofPatte
  • MySQL 5.5:对于 innodb 中的 text/varchar 字段,以下哪一项是更好的存储方式?

    要求 Page 1 gt 显示用户及其最新 10 篇博客文章的 1 2 行预览 Page 2 gt 显示带有全文的单个博客文章 方法一 MySQL table gt userid gt varchar 50 post id gt integ