TINYTEXT 作为 MySQL 中的主键?

TINYTEXT as a PRIMARY key in MySQL?

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

根据我对文档的有限理解,主键的 Size 可用于简化检测唯一值的方法,即当前几个字符(由 Size 指定)足以认为它是独一无二的匹配。在我的例子中,size 会从 5 到 10 不等(它们都是 latin1,所以它们是每个字符的精确字节 + 1 的长度)。两个问题:

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

对于 TINYTEXT 无法指定大小。使用 VARCHAR(大小)

SQL Data Types

  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。它比在 table(WHERE、JOINS 等)中使用整数进行搜索需要更多 more processing time。 link 很旧但仍然相关;

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

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

仅供参考,您无法在 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 |
+-----------+