MySQL在varchar大小之间是否存在性能差异?例如varchar(25)
和varchar(64000)
。如果不是,是否有理由不声明所有具有最大大小的varchar,只是为了确保您不会用完空间?
MySQL在varchar大小之间是否存在性能差异?例如varchar(25)
和varchar(64000)
。如果不是,是否有理由不声明所有具有最大大小的varchar,只是为了确保您不会用完空间?
Answers:
您必须意识到使用CHAR与VARCHAR的权衡
使用CHAR字段,您分配的正是您所获得的。例如,无论您在字段中放置的字符如何,CHAR(15)都会分配并存储15个字节。字符串操作简单明了,因为数据字段的大小是完全可以预测的。
使用VARCHAR字段,您将获得完全不同的故事。例如,VARCHAR(15)实际上动态分配最多16个字节,最多动态分配15个数据,并至少分配1个额外的字节来存储数据的长度。如果要存储的字符串'hello'将占用6个字节,而不是5个字节。在所有情况下,字符串操作都必须始终执行某种形式的长度检查。
当您做两件事时,这种折衷会更加明显:
1.存储数百万或数十亿行
2.索引为CHAR或VARCHAR的列
显然,VARCHAR拥有优势,因为可变长度数据将产生较小的行,从而产生较小的物理文件。
由于CHAR字段由于具有固定的字段宽度而需要较少的字符串操作,因此针对CHAR字段的索引查找平均比VARCHAR字段快20%。我这不是任何猜想。《MySQL数据库设计和调优》这本书在MyISAM表上做了出色的工作来证明这一点。本书中的示例执行了以下操作:
ALTER TABLE tblname ROW_FORMAT=FIXED;
此指令强制将VARCHAR用作CHAR。我在2007年的上一份工作中做到了这一点,并使用了300GB的表,并将索引查找速度提高了20%,而没有进行任何其他更改。它像出版一样工作。但是,它的确产生了几乎两倍大的表,但这只是权衡第一。
您可以分析所存储的数据,以查看MySQL对列定义的建议。只需对任何表运行以下命令:
SELECT * FROM tblname PROCEDURE ANALYSE();
这将遍历整个表,并根据其包含的数据,最小字段值,最大字段值等为每列推荐字段定义。有时,您只需要在规划CHAR与VARCHAR时使用常识。这是一个很好的例子:
如果要存储IP地址,则该列的掩码最多为15个字符(xxx.xxx.xxx.xxx)。我会心跳一跳,直接跳到CHAR(15),因为IP地址的长度变化不会太大,而且字符串操作的复杂性由一个额外的字节控制。您仍然可以对这样的列执行PROCEDURE ANALYSE()。它甚至可能建议使用VARCHAR。在这种情况下,我的钱仍将超过VARCHAR放在CHAR上。
CHAR与VARCHAR问题只有通过适当的计划才能解决。强大的力量伴随着巨大的责任(陈词滥调,但事实如此)
答案实际上是相当复杂的。简短的版本:有区别。
当创建临时表以过滤结果(例如GROUP BY
语句)时,将分配全长。
有线协议(向客户端发送行)可能会分配更大的长度。
存储引擎可能/可能未实现适当的varchar。
对于(2),我承认我并不是很熟悉wire协议,但是这里的一般建议是尝试并至少花一些力气来猜测长度。
该线程中的大多数答案都使用5年,是在InnoDB和utf8为默认值之前编写的。所以,让我重新开始...
当查询需要内部临时表时,它将尝试使用MEMORY
表。但是如果以下情况不能使用MEMORY
TEXT
/ BLOB
正在获取的列,甚至没有TINYTEXT
。VARCHAR
大于某个数量,在当前版本中可能为512。另外,请注意VARCHARs
将变成了CHARs
。因此,VARCHAR(255)
用CHARACTER SET utf8
膨胀到765个字节,无论是什么在列。然后,这可能会触发:
MEMORY
表大于max_heap_table_size
或 tmp_table_size
,它将转换为MyISAM并可能溢出到磁盘。因此,VARCHAR(25)
更有可能停留MEMORY
,从而更快。 (255)
不好,也(64000)
很糟糕。
(将来,临时表可能是InnoDB
,并且此答案的一部分将需要修改。)
大小的varchar列使整个表上的查询更有可能使用临时表。根据高性能MySQL的书。当优化器尝试查看它是否可以在内存中运行此查询或是否需要临时表时,它会根据表定义查看行大小,这意味着,为了提高速度,它不会尝试查看64K字符中的多少您实际上在使用。这就是为什么作者建议您不要将该定义方式扩展到超出该列中的实际可能值的范围。显然,如果您为进入临时表的更多查询做好了准备(即使实际数据大小可以容纳在RAM中),那么您现在可能会遭受I / O损失。
据我了解,较小的字段可能直接包含在索引中,而较长的字段则不能。由于该限制,如果您希望字符串可索引,请说使它们更短。否则,不然,无论字段是25还是MAX,因为它们都是varchar,然后像排序或比较之类的操作将在相同的时间内运行。