【问题标题】:MySQL/PostgreSQL Column Sizes, Why?MySQL/PostgreSQL 列大小,为什么?
【发布时间】:2018-02-11 02:22:50
【问题描述】:

我正在开发一个程序并遇到了一个错误,即在表列中插入一个类型为 int 的值,并且该值大于 Integer.MAX_VALUE 它吐出一个错误说数字太大。我读到解决这个问题的方法很简单,只是将表更改为 BigInt,这应该可以解决它。但这让我想,为什么不是所有的程序员都只使用最大列值(例如 Varchar(255)、BigInt 等)而不是像 Varchar(30) 或 Int 这样的更小的值?

当您不确定要插入什么内容时,尤其是如果它基于用户输入时,这不会几乎完全消除像我这样的错误吗?仅使用列所需的最大可能类型有什么缺点吗?即使你在一个大的 int 列中只有“2”,表的大小也会更大(即使这适用于 int?)。有没有性能损失?

谢谢!

【问题讨论】:

  • 您使用的是哪个数据库?
  • 编辑你的问题标签和你正在使用的实际数据库标签。
  • @TimBiegeleisen 是对的,这类问题没有通用答案,只有各种数据库特定的答案。
  • varchar(255) 绝对不是 varchar 列的“最大列大小”。

标签: mysql sql-server postgresql performance


【解决方案1】:

为什么不是所有程序员都只使用最大列值(例如 Varchar(255)、BigInt 等),而不是更小的东西 Varchar(30) 还是 Int?

有些人正是这样做的。看到开发人员也将数字或日期/时间值存储在 varchar 列中也并不罕见。

我经常看到性能和存储成本是不这样做的原因。这些是考虑因素(因 DBMS 而异),但关系数据库领域中更重要的一个因素是数据完整性。选择的数据类型是数据模型的关键部分,因为它决定了可以存储的数据域。最重要的是,关系数据库提供检查、引用和 NULL 约束来进一步限制列值。

这不会几乎完全消除像我这样的错误发生吗 当你不确定要插入什么时,特别是如果它是 基于用户输入?

当然可以,但是为什么要停留在 64 位整数上呢?为什么不是 NUMERIC(1000)?这是一个反问,要指出必须了解业务领域才能正确建模数据并执行验证规则。一个 64 位整数对于存储一个人的孩子数量肯定是大材小用,但由于数据输入粗心,您最终可能会得到数十亿的值。列数据类型是不良数据的最后一道防线,当它基于用户输入时尤为重要。

话虽如此,我们可以将 RDBMS 用作无用的存储引擎,并在应用程序代码中强制执行数据完整性规则(如果有)。在这种情况下,存储和性能是唯一的考虑因素。

【讨论】:

    【解决方案2】:

    除了 SQL Server,我不能与任何 RDBMS 对话(但我想这适用于所有 RDBMS)... BIG INT 占用的空间是 INT 的两倍...这意味着更少的数据适合一个页面意味着缓存中的数据越少意味着性能越慢。

    在 SQL Server 中实际上有 4 种 INT 类型:

    TINYINT(1 字节),

    SMALLINT(2 个字节),

    INT(4 字节),

    BIGINT(8 字节)。

    优秀的数据库开发人员会非常谨慎地根据预期放入列中的数据选择合适的数据类型。除了存储空间的问题外,数据类型还起到数据约束的作用。因此,如果我选择 TINYINT 作为我的数据类型,这意味着我只希望看到 0 到 255 之间的值,并且会拒绝任何超出该范围的值。

    如果同事要提交包含所有 VARCHAR(255) 和 BIGINT 的表格设计,我会拒绝它并让他们适当地调整所有内容。这样的想法很懒惰,这会在房子的数据库方面造成巨大的问题。

    【讨论】:

    • 我现在了解情况了。当您提到一位优秀的数据库开发人员评估可能的情况并选择最佳结果时,如果他处于我的情况怎么办?我不能肯定地告诉你输出,但我知道在我自己的测试中有一些情况(比如说 1/20 次)代码试图插入大于 Integer.MAX_VALUE 的东西。开发人员会直接使用 BIGINT 还是做一些鬼鬼祟祟的事情,比如存储长度小于 bigint 的 varchar,然后将其转换为字符串,反之亦然?
    • 在我开始更改数据类型之前,我至少会尝试找出违规值的来源并确保它是合法值。鉴于 INT 数据类型可以保存从 -2,147,483,647 到 2,147,483,647 的值,超出该范围的值至少会引起注意。如果我的程序只是生成随机数,我倾向于缩小允许范围而不是切换到 BIGINT。另外,我并不是说 BIGINT 永远不合适。我只是说,只在合适的时候使用它。
    • 如果 BIGINT 在您正在处理的特定情况下是合适的,那么请务必使用它...但是...这不是您的 OP 的重点。您提出了一个问题,“为什么不是所有程序员都只使用最大列值(例如 Varchar(255)、BigInt 等)而不是像 Varchar(30) 或 Int 这样的更小的值?”这就是我要解决的问题。
    • @Nicster15 我完全同意 Jason A. Long 的观点。话虽如此,我想补充以下方面:显然,您对您的代码尝试插入不适合INT 的值感到惊讶。这表明它没有以正确的方式检查用户输入,或者它包含其他错误。因此,即使您更改为 BIGINT,您的代码仍有可能尝试插入甚至不适合的值。因此,我建议您检查您的申请,直到您完全了解问题的原因并在之后做出决定。
    【解决方案3】:

    对于 Varchar,您通常不只使用 MAX 的原因是因为它以不同的方式存储它并且限制了您的索引维护操作。例如,您不能使用 varchar(max) 字段“在线”重建索引。虽然涉及到一点点挥手,但基本上 varchar(max) 数据被存储在行外,因此维护额外的数据存储存在开销。

    对于数字类型,主要是空格。 Bigint 是一个 8 字节有符号整数,而 int 只有 4 个字节。如果您不需要大于 24 亿的空间,那只是浪费空间(如果您有 24 亿行数据,通常会浪费很多空间)。

    数据压缩可以解决其中的一些问题,但并非没有在查询数据时必须解压缩数据的成本。

    因此原因多种多样,但除了使用更大尺寸的 varchar(不是 varchar(max))可能例外,为您的数据选择“正确”的数据类型只是一个好主意。

    【讨论】:

    • 感谢您提供的信息!你建议我怎么做?我需要以某种方式在我的表中存储大于 int 的数字,但并非总是如此(可能是 1/20 倍)。
    • 您认为在发布答案之前找出 OP 正在使用的数据库是个好主意吗?
    • 如果你需要大整数,你需要大整数。如果需要,使用它并没有错。您只是不想在不使用时自动使用 bigint。如果您需要非常大的数字,您可以查看浮点数
    • @TimBiegeleisen 你认为建议会改变吗?
    • MySQL 甚至没有 varchar max,我敢打赌每个数据库的答案会有很大差异。
    猜你喜欢
    • 2022-01-24
    • 1970-01-01
    • 2021-11-11
    • 2018-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-13
    • 2014-02-25
    相关资源
    最近更新 更多