Answers:
发生错误是因为MySQL只能索引BLOB或TEXT
列的前N个字符。所以错误主要发生时,有一个领域/列类型TEXT
或BLOB或那些属于TEXT
或BLOB
类型,如TINYBLOB
,MEDIUMBLOB
,LONGBLOB
,TINYTEXT
,MEDIUMTEXT
,和LONGTEXT
您尝试使一个主键或索引。无论长度是完整的BLOB
还是TEXT
没有长度的,MySQL都无法保证列的唯一性,因为它具有可变和动态大小。因此,当使用BLOB
or TEXT
类型作为索引时,必须提供N的值,以便MySQL可以确定键的长度。但是,MySQL不支持TEXT
或上的密钥长度限制BLOB
。TEXT(88)
根本行不通。
当您尝试将表列从non-TEXT
和non-BLOB
类型(如VARCHAR
和ENUM
转换为TEXT
或BLOB
类型)转换为错误,并且该列已被定义为唯一约束或索引时,也会弹出该错误。Alter Table SQL命令将失败。
该问题的解决方案是从索引或唯一约束中删除TEXT
或BLOB
列,或将另一个字段设置为主键。如果您不能这样做,并且想对TEXT
or BLOB
列设置限制,请尝试使用VARCHAR
type并对其限制长度。默认情况下,VARCHAR
最大限制为255个字符,并且必须在声明后的括号内隐式指定其限制,即,VARCHAR(200)
将其限制为仅200个字符长。
有时,即使您没有在表中使用TEXT
或BLOB
相关类型,也可能会出现错误1170。例如,当您将VARCHAR
列指定为主键,但是错误地设置了它的长度或字符大小时,就会发生这种情况。VARCHAR
最多只能接受256个字符,因此,诸如此类的任何操作都VARCHAR(512)
将迫使MySQL自动将其转换VARCHAR(512)
为SMALLTEXT
数据类型,如果将该列用作主键或唯一或非唯一索引,则该操作随后将在键长度上出现错误1170。要解决此问题,请指定小于256的数字作为VARCHAR
字段的大小。
您应该定义TEXT
要索引的列的前导部分。
InnoDB
768
每个索引键的字节数限制,并且您创建索引的时间不能超过该长度。
这将正常工作:
CREATE TABLE t_length (
mydata TEXT NOT NULL,
KEY ix_length_mydata (mydata(255)))
ENGINE=InnoDB;
请注意,键大小的最大值取决于列字符集。它767
是单字节字符集(例如)的字符,LATIN1
并且仅255
用于UTF8
(MySQL
仅用于每个字符BMP
最多需要3
字节的)字符
如果您需要将整个列作为PRIMARY KEY
,请计算SHA1
或MD5
散列并将其用作PRIMARY KEY
。
REDUNDANT
或COMPACT
行格式的InnoDB表,索引键前缀长度限制为767个字节。例如,假设utf8mb3字符集且每个字符最多3个字节,则您可能在a TEXT
或VARCHAR
列上使用超过255个字符的列前缀索引来达到此限制。 REDUNDANT
并且COMPACT
是给出此答案时唯一可用的格式。
MySQL不允许索引BLOB
,TEXT
和长VARCHAR
列的完整值,因为它们包含的数据可能很大,并且隐式地DB索引会很大,这意味着无法从索引中受益。
MySQL要求您定义要索引的前N个字符,诀窍是选择一个数字N,该数字足够长以提供良好的选择性,但又足够短以节省空间。前缀应该足够长,以使索引几乎与索引整个列时一样有用。
在继续之前,让我们定义一些重要的术语。索引选择性是总的不同索引值与总行数之比。这是测试表的一个示例:
+-----+-----------+
| id | value |
+-----+-----------+
| 1 | abc |
| 2 | abd |
| 3 | adg |
+-----+-----------+
如果我们仅索引第一个字符(N = 1),那么索引表将如下表所示:
+---------------+-----------+
| indexedValue | rows |
+---------------+-----------+
| a | 1,2,3 |
+---------------+-----------+
在这种情况下,指数选择性等于IS = 1/3 = 0.33。
现在让我们看看如果将索引字符的数量增加到两个(N = 2)会发生什么。
+---------------+-----------+
| indexedValue | rows |
+---------------+-----------+
| ab | 1,2 |
| ad | 3 |
+---------------+-----------+
在这种情况下,IS = 2/3 = 0.66,这意味着我们增加了索引的选择性,但同时也增加了索引的大小。关键是要找到的最小数N,这将导致以最大的索引选择性。
您可以通过两种方法对数据库表进行计算。我将在此数据库转储上进行演示。
假设我们要在表employees中添加列last_name到索引,并且要定义最小的数字N,它将产生最佳的索引选择性。
首先,让我们确定最常用的姓氏:
select count(*) as cnt, last_name
from employees
group by employees.last_name
order by cnt
+-----+-------------+
| cnt | last_name |
+-----+-------------+
| 226 | Baba |
| 223 | Coorg |
| 223 | Gelosh |
| 222 | Farris |
| 222 | Sudbeck |
| 221 | Adachi |
| 220 | Osgood |
| 218 | Neiman |
| 218 | Mandell |
| 218 | Masada |
| 217 | Boudaillier |
| 217 | Wendorf |
| 216 | Pettis |
| 216 | Solares |
| 216 | Mahnke |
+-----+-------------+
15 rows in set (0.64 sec)
如您所见,姓Baba是最常用的。现在,我们将查找最常见的last_name前缀,从五个字母的前缀开始。
+-----+--------+
| cnt | prefix |
+-----+--------+
| 794 | Schaa |
| 758 | Mande |
| 711 | Schwa |
| 562 | Angel |
| 561 | Gecse |
| 555 | Delgr |
| 550 | Berna |
| 547 | Peter |
| 543 | Cappe |
| 539 | Stran |
| 534 | Canna |
| 485 | Georg |
| 417 | Neima |
| 398 | Petti |
| 398 | Duclo |
+-----+--------+
15 rows in set (0.55 sec)
每个前缀出现的次数更多,这意味着我们必须增加数字N,直到值几乎与前面的示例相同为止。
这是N = 9的结果
select count(*) as cnt, left(last_name,9) as prefix
from employees
group by prefix
order by cnt desc
limit 0,15;
+-----+-----------+
| cnt | prefix |
+-----+-----------+
| 336 | Schwartzb |
| 226 | Baba |
| 223 | Coorg |
| 223 | Gelosh |
| 222 | Sudbeck |
| 222 | Farris |
| 221 | Adachi |
| 220 | Osgood |
| 218 | Mandell |
| 218 | Neiman |
| 218 | Masada |
| 217 | Wendorf |
| 217 | Boudailli |
| 216 | Cummings |
| 216 | Pettis |
+-----+-----------+
这是N = 10的结果。
+-----+------------+
| cnt | prefix |
+-----+------------+
| 226 | Baba |
| 223 | Coorg |
| 223 | Gelosh |
| 222 | Sudbeck |
| 222 | Farris |
| 221 | Adachi |
| 220 | Osgood |
| 218 | Mandell |
| 218 | Neiman |
| 218 | Masada |
| 217 | Wendorf |
| 217 | Boudaillie |
| 216 | Cummings |
| 216 | Pettis |
| 216 | Solares |
+-----+------------+
15 rows in set (0.56 sec)
这是非常好的结果。这意味着我们可以在last_name
仅索引前10个字符的列上建立索引。在表定义中,列last_name
定义为VARCHAR(16)
,这表示每个条目我们已保存6个字节(如果姓氏中包含UTF8字符,则节省更多字节)。在此表中,有1637个不同的值乘以6个字节,大约为9KB,并想象如果我们的表包含一百万行,这个数字将如何增长。
您可以阅读计算多种其他方式ñ在我的岗位在MySQL前缀索引。
将索引添加到具有文本类型列的表时出现此错误。您需要声明每种文本类型要使用的大小量。
将大小金额放在圆括号()内
如果使用了太多字节,则可以在括号中声明varchar的大小,以减少用于索引的数量。即使您为已经像varchar(1000)这样的类型声明了大小,也是如此。您无需像其他人一样创建新表。
添加索引
alter table test add index index_name(col1(255),col2(255));
添加唯一索引
alter table test add unique index_name(col1(255),col2(255));
alter table authors ADD UNIQUE(name_first(767), name_second(767));
注意:767是MySQL在处理blob / text索引时将索引列的最大字符数限制
参考:http : //dev.mysql.com/doc/refman/5.7/en/innodb-restrictions.html
解决此问题的另一种极好的方法是创建没有唯一约束的TEXT字段,并添加一个唯一的同级VARCHAR字段,并包含TEXT字段的摘要(MD5,SHA1等)。在插入或更新TEXT字段时,计算并存储整个TEXT字段的摘要,然后在整个TEXT字段(而不是某些开头部分)上具有唯一性约束,可以快速搜索该约束。
到目前为止,没有人提到它... utf8mb4是4字节,还可以存储图释(我们永远不应该再使用3字节的utf8),并且可以避免出现诸如Incorrect string value: \xF0\x9F\x98\...
不应该使用典型的VARCHAR(255)而是VARCHAR( 191),因为如果utf8mb4和VARCHAR(255)的同一部分数据存储在页面外,则不能为VARCHAR(255)列创建索引,但可以为VARCHAR(191)创建索引。这是因为ROW_FORMAT = COMPACT或ROW_FORMAT = REDUNDANT的最大索引列大小为767字节。
对于较新的行格式ROW_FORMAT = DYNAMIC或ROW_FORMAT = COMPRESSED(需要较新的文件格式innodb_file_format = Barracuda而不是较早的Antelope),最大索引列大小为3072。当innodb_large_prefix = 1时,MySQL> = 5.6.3可用(默认情况下禁用) MySQL <= 5.7.6,默认情况下已启用MySQL> = 5.7.7)。因此,在这种情况下,我们可以为utf8mb4使用VARCHAR(768)(对于旧的utf8使用VARCHAR(1024))作为索引列。从5.7.7版本开始,不推荐使用innodb_large_prefix选项,因为它的行为是内置的MySQL 8(在此版本中,该选项已删除)。
转到mysql- edit table
>将列类型更改为varchar(45)
。
这样使用
@Id
@Column(name = "userEmailId", length=100)
private String userEmailId;
UNIQUE
键?