【问题标题】:MySQL Field Space AllocationMySQL 字段空间分配
【发布时间】:2016-08-01 14:17:51
【问题描述】:

首先我在我的应用程序上创建一个模型,然后 Entity Framework 生成用于创建表的 SQL。 第一个生成varchar(20) 类型的列,第二个生成longtext

示例

[StringLength(20)]
public string Code { get; set; }

public string CodeTwo { get; set; }

问题

这两个声明有什么区别(空间分配)? (即使它们存储相同的值,例如具有 5 个字符的“test”。)

如果我知道一个字段的长度在 10-15 个字符之间存在差异,那么最好的方法是限制最大长度还是让它“无限”(空间分配)?

提前致谢。 对不起我的英语不好。

【问题讨论】:

    标签: c# mysql sql entity-framework


    【解决方案1】:

    用户@Marconcílio Souza 的翻译答案,用另一种语言提出的同一个问题。

    当实体框架在您的数据库中生成表时,它会检查每个字段的类型,对于 STRING 类型,当您指定大小时,它会对具有相应类型的银行进行相同的规范。

    就其而言

    [StringLength (20)]
    public string Code {get; set; }
    

    对应的MySQL是varchar(20),但是当相同的string类型和声明时没有固定大小的Entity Framework在MySQL和longtext的情况下在数据库中尽可能多地为这种类型分配。

    BLOB 类型为 LONGTEXT 的列本质上是可变长度的,不使用时几乎不占用存储空间。在使用'text'测试'set'分配和传递字符串的大小的情况下,即使是NULL值也不影响它们所需的空间。

    * BLOB 与 VARCHAR 的优缺点 *

    本段中所有引用 VARCHAR 类型的 cmets 对 CHAR 类型也有效。 每条注释都以 BLOB + 或 VARCHAR + 标记结尾,表示哪种类型的数据更好。


    - 您知道数据的最大长度吗?

    对于 VARCHAR,您需要声明链的最大长度。 使用 blob,您不必担心。 BLOB +


    • 您需要存储很长的字符串?

    单个 VARCHAR 限制为 32K 字节(即大约 10,000 个 Unicode 字符)。 最大大小为 blob(根据服务指南);

      - 页面大小 1kb => 64 Mb - 页面大小 2kb => 512 Mb - 页面大小为 4 KB => 4Gb - 页面大小为 8KB => 32Gb

    BLOB +


    • 您需要在单个表中存储许多长文本列?

    总行长(未压缩)限制为 64K。 VARCHAR 是直接在线存储的,因此您不能连续存储许多长字符串。 Blob 由它们的 blob-id 表示,并且仅使用 64K 最大值中的 8 个字节。 BLOB +


    • 您想尽量减少客户端和服务器之间的调用?

    VARCHAR 数据在搜索操作中与其他行数据一起获取,并且通常同时通过网络发送多行数据。 每个 blob 都需要进行额外的搜索操作open / fetch。 VARCHAR +


    • 您想尽量减少客户端和服务器之间传输的数据量吗?

    blob 的优点是获取行你只得到 blob-id,所以你可以决定是否寻找 BLOB 数据。 在旧版本的 InterBase 中存在一个问题,即 VARCHAR 以声明的全长通过网络发送。此问题已在 Firebird 1.5 和 InterBase 6.5 中得到修复。 绘制(BLOB + 用于旧版本的服务器)


    • 您想尽量减少使用的空间吗?

    VARCHAR 被压缩为 RLE(实际上整行都被压缩,除了 blob)。最多可以将 128 个字节压缩为 2 个字节。这意味着即使是空的 varchar (32000) 也会占用 500 + 2 个字节。

    Blob 没有被压缩,但是空的(即 null)blob 将只占用 8 个字节的 blob-id(稍后会被 RLE 压缩)。非空 blob 可以与该行中的其他数据(如果适用)存储在同一页面上,也可以存储在单独的页面中。适合数据页的小 blob 的开销为 40 字节(或更多)。大 blob 在数据页中具有相同的 40 字节开销,加上每个 blob 页上的 28 字节开销(第一个为 30 字节)。一个 blob 页不能包含多个 blob(即 blob 页不作为数据页共享)。例如。对于 4K 页面大小,如果存储 5K blob,则会分配两个 blob 类型的页面,这意味着您损失了 3K 空间!换句话说 - 页面大小越大,小 blob 适合数据页面的可能性就越高,但如果大 blob 需要单独的 blob 页,也会浪费更多的空间。 VARCHAR +(声明长度非常大的 VARCHAR 或具有大量 NULL blob 的表除外)


    • 您需要包含大量行数的表格?

    每一行由DB_KEY标识,是一个64位的值,32位,32位,平衡ID用来定位行。表中的最大理论行数为 2 ^ 32(但由于各种原因,最大 true 甚至更低)。 Blob -IDS 是从与 DB_KEYs 相同的地址空间分配的,这意味着表中的 blob 越多,面对队列的 DB_KEY 就越少。另一方面,当存储的行很宽时(例如,它们包含长 VARCHAR),则适合数据页的行数较少,并且许多 DB_KEY 值仍然未签名。 varchar +?


    • 你想要一个好的表现?

    因为大块存储在数据页之外,它们增加了数据页的“密度”行效率并因此缓存(减少了搜索期间的 I/O 操作次数)。 BLOB +


    • 您需要对文本列的内容执行搜索吗?

    在VARCHAR中可以使用'='、'>'等运算符,其中of()、区分大小写的as和不区分大小写的CONTAINING。大多数情况下可以使用索引来加快搜索速度。 Blob 无法被索引,并且您仅限于 TASTE、启动和包含运算符。您不能直接将 blob 与运算符 '='、'>' 等进行比较(除非您使用 UDF),因此您不能,例如,在 Blob 字段中连接表。 VARCHAR +


    • 您想用 CONTAINING 搜索这些文本的内容吗?

    Containig 可用于执行不区分大小写的搜索内容 VARCHAR 字段。 (不使用索引) 因为不能为 BLOB 列设置排序规则,所以不能在 BLOB 列中对国家字符使用完全不区分大小写的搜索(只有字符集的下半部分不区分大小写)。 (或者,您可以使用 UDF)。 Firebird 2 已经允许您设置文本换行(和二进制)列。 VARCHAR +


    • 您需要文本列的大写内容吗?

    您可以在 varchar 上使用内置的 UPPER () 函数,但不能在 blob 上使用。 (此外,CAST、MIN、MAX 不能与 blob 一起使用) VARCHAR +


    您不能按 blob 列排序。 (E GROUP BY、DISTINCT、UNION、JOIN ON) 无法连接 blob 列。 VARCHAR +


    没有用于将 blob 转换为 VARCHAR 或将 VARCHAR 转换为 blob 的内置转换函数 (CAST)。 (但您可以为此目的编写 UDF。) 从 Firebird 1.5 开始,您可以使用内置的 SUBSTRING 函数将 blob 转换为 VARCHAR(但 FROM 子句不能超过 32K)。 画画


    您不能在 SQL 命令中直接为 blob 赋值, 例如。输入值指南(MyBlob)('abc'); (但您可以使用 UDF 将字符串转换为 blob)。 VARCHAR +

    Firebird - 0.9.4 已经有这个功能 画画


    • 您需要对这些文本列进行良好的安全保护吗?

    要恢复表数据,您必须被授予 SELECT 权限。 要检索 blob,您只需要知道 blob -id(存储在表中),但 Firebird / InterBase 不会检查您是否拥有任何 blob 表权限。这意味着知道或猜到正确 blob -id 的每个人都可以在没有任何权限的情况下读取 blob。 (您可以使用 ISQL 和 BLOBDUMP 命令进行尝试。) VARCHAR +


    更多细节

    Reference 1

    Reference 2

    Reference 3

    Reference 4

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多