这完全取决于所使用的 DBMS 引擎。SQL 本身并没有规定如何物理存储事物,只规定如何在逻辑上查看它们。
例如,您的 DBMS 可能会在行中为最大大小分配空间,加上一些额外的字节来存储长度。在这种情况下,和之间会有很大的不同varchar(10)
,varchar(1000)
因为每行会浪费相当多的空间。
或者,它可以为varchar
数据使用缓冲池,并在行中仅存储长度和缓冲池“起始地址”。在这种情况下,每一行都会为一varchar
列存储相同大小的信息,而不管它的大小,但是会有一个额外的步骤来提取该列中的实际数据(按照指向缓冲池的链接)。
您使用 a 的原因varchar
正是它被命名为的原因varchar
。它允许您存储可变大小的数据元素。通常,char(10)
无论如何都会给您十个字符,如果您插入较短的内容,则用空格填充它。您可以在提取时修剪尾随空格,但如果您要存储的数据实际上是"hello "
,并且您希望保留尾随空格,则效果不佳。
一个不错的 DBMS 引擎可能会决定根据列的最大大小进行权衡varchar
。对于简短的,它可以将其内联存储在行中并消耗额外的字节大小。
较长varchar
的列可以“外包”到一个单独的缓冲池,以确保行读取保持高效(至少在您需要大varchar
列之前)。
您需要做的是针对您的特定 DBMS 重新提出问题,以获得更有针对性的答案。
或者,老实说,将您的数据库设计为仅存储最大大小。如果你知道它是 10,那就太varchar(1000)
浪费了。如果将来您需要扩大列,那就是时候做,而不是现在(参见YAGNI)。
对于 MySQL,您需要查看Chapter 14 Storage Engines
在线文档。
它涵盖了 MySQL 使用的各种存储引擎(例如 InnoDB 和 MyISAM),并且如果深入了解,您可以看到信息是如何物理存储的。
例如,在 MyISAM 中,表(varchar
包含)中存在可变长度数据通常意味着动态表。这遵循了一个大致类似于我上面提到的缓冲池概念的方案,其优点是为可变大小的列浪费的空间更少,而缺点是行可能会变得碎片化。
另一种存储格式(不考虑压缩格式,因为它只真正用于只读表)是静态格式,其中数据存储在单个物理行中。
关于 InnoDB 物理结构的信息可以在这里找到。根据您使用的是 Antelope 还是 Barracuda 文件格式,您最终会遇到“所有信息都是物理行”或“缓冲池”的情况,类似于 MyISAM 对动态和静态的区分。