【问题标题】:TINYTEXT as a PRIMARY key in MySQL?TINYTEXT 作为 MySQL 中的主键?
【发布时间】:2020-07-11 20:09:34
【问题描述】:

表中的条目由 5-10 个字符长的单词唯一标识,我使用 TINYTEXT(10) 作为列。但是,当我尝试将其设置为 PRIMARY 键时,我收到 size 丢失的错误。

根据我对文档的有限理解,PRIMARY 键的Size 可用于简化检测唯一值的方法,即当前几个字符(由Size 指定)足以将其视为唯一匹配时。在我的情况下,size 的值从 5 到 10 不等(它们都是 latin1,因此它们是每个字符的精确字节 + 长度为 1)。两个问题:

  1. 如果我想使用 TINYTEXT 作为主键,我应该指定哪个size?最大可用 - 在这种情况下为 10?或者应该是 size strictly EXACT,例如,如果我的密钥是 6 个字符长的单词,但我将 Size 指定为 PK 为 10 - 它会尝试读取所有 10 个并且会失败给我一个例外?
  2. 使用 [TINY]TEXT 进行 PK 在性能方面会有多糟糕?所有 Google 搜索结果都让我得出“这很糟糕,你被解雇了”的意见和陈述,但考虑到 TINYTEXT 最大为 255 并且我已经将最大长度指定为 10,在这种情况下真的如此吗?

【问题讨论】:

  • 您是否有理由认为使用 TINYTEXT 而不是 VARCHAR?
  • @gview 是的,我不需要超过 10 个字符,并且 TINYTEXT 没有填充 255 长。 VARCHAR 有自己的打包问题,因为它长达 65k
  • varchar 只需要使用的存储空间 + 1 个字节的长度。它不像一个字符。如果您声明一个 varchar[10],您最多可以存储 10 个字符,但是如果您只使用 5,那么它只需要 5 + 1 个字节。更糟糕的情况是需要 11 个字节。
  • @gview - 最坏的情况是 41 字节 -- 如果 charset = utf8mb4。
  • 使用VARCHAR,而不是TINYTEXT。并且不要使用前缀。期间。

标签: php mysql database tinytext


【解决方案1】:
  1. MySQL/MariaDB 只能索引文本字段的第一个字符,如果太大,则不能索引整个文本。最大密钥大小为 3072 字节,任何大于该大小的文本字段都不能用作 KEY。因此,对于超过 3072 字节的文本字段,您必须明确指定它将索引多少字符。使用 VARCHAR 或 CHAR 时可以直接完成,因为您在声明数据类型时显式设置它。 *TEXT 不是这种情况——他们没有那个选项。解决方案是像这样创建主键:

    CREATE TABLE mytbl (
        name TEXT NOT NULL,
        PRIMARY KEY idx_name(name(255))
    );
    

    如果您需要在大于 3072 字节的 VARCHAR 字段、BINARY 字段和 BLOB 上创建主键,则可以使用相同的技巧。无论如何,您可以想象,如果两个大而不同的文本在开头的前 3072 个字节处以相同的字符开头,那么它们将被系统视为相等。这可能是个问题。

  2. 使用文本字段作为主键通常是个坏主意。有两个原因:

    2.1。 more processing time 比使用整数在表中搜索(WHERE、JOINS 等)需要更多的时间。该链接已旧但仍然相关;

    2.2。另一个表中的任何外键都必须具有与主键相同的数据类型。当你使用文本时,这会浪费磁盘空间;

注意:*TEXT 和 VARCHAR 的区别在于 *TEXT 字段的内容不存储在表内,而是存储在外部内存位置。通常我们会在需要存储非常大的文本时这样做。

【讨论】:

  • 我编辑了我的答案,因为我的第一个版本点 1 不正确(我说它不能完成)。确实可以:)
  • “使用文本字段作为主键通常是个坏主意”——是的,避免使用 TEXT 作为主键。如果您碰巧有两行具有不同 TEXT 值的行在开头共享完全相同的 3072 个字符,则 INSERT 将 [错误地] 失败,
【解决方案2】:

对于 TINYTEXT 不能指定大小。使用 VARCHAR(大小)

SQL Data Types

【讨论】:

  • 您不指定字段的最大大小,但您可以指定索引的大小。看看我对这个问题的回答。
【解决方案3】:

仅供参考,您不能在 MySQL 中为 TINYTEXT 指定大小:

mysql> create table t1 ( t tinytext(10) );
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds 
to your MySQL server version for the right syntax to use near '(10) )' at line 1

您可以在TEXT 之后指定一个长度,但它并不像您想象的那样工作。这意味着它将选择 TEXT 类型家族中的一种,即支持至少您要求的长度的最小类型。但是一旦这样做,它就不会限制输入的长度。它仍然接受不超过它选择的类型的最大长度的任何数据。

mysql> create table t1 ( t text(10) );
Query OK, 0 rows affected (0.02 sec)

mysql> show create table t1\G
*************************** 1. row ***************************
       Table: t1
Create Table: CREATE TABLE `t1` (
  `t` tinytext
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

mysql> insert into t1 set t = repeat('a', 255);
Query OK, 1 row affected (0.01 sec)

mysql> select length(t) from t1;
+-----------+
| length(t) |
+-----------+
|       255 |
+-----------+

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-30
    • 2015-11-13
    • 1970-01-01
    相关资源
    最近更新 更多