我有一个主键为varchar(255)的表。在某些情况下,255个字符是不够的。我尝试将字段更改为文本,但我得到以下错误:
BLOB/TEXT column 'message_id' used in key specification without a key length
我该如何解决这个问题?
编辑:我还应该指出,这个表有一个多列的复合主键。
我有一个主键为varchar(255)的表。在某些情况下,255个字符是不够的。我尝试将字段更改为文本,但我得到以下错误:
BLOB/TEXT column 'message_id' used in key specification without a key length
我该如何解决这个问题?
编辑:我还应该指出,这个表有一个多列的复合主键。
当前回答
DROP该表并再次运行Spring Project。 这可能会有所帮助。 有时你重写了foreignKey。
其他回答
另外,如果你想在这个字段中使用索引,你应该使用MyISAM存储引擎和FULLTEXT索引类型。
不要用长值作为主键。这会毁了你的表现。请参阅mysql手册,第13.6.13节“InnoDB性能调优和故障排除”。
相反,使用一个代理int键作为主键(使用auto_increment),并使用长键作为辅助UNIQUE。
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)
如你所见,姓巴巴的人出现频率最高。现在我们要找出最常出现的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,想象一下,如果我们的表包含数百万行,这个数字将如何增长。
你可以在我的文章中阅读其他计算N的方法。
DROP该表并再次运行Spring Project。 这可能会有所帮助。 有时你重写了foreignKey。
我知道现在已经很晚了,但是删除唯一键约束解决了这个问题。我没有使用TEXT或LONGTEXT列作为PK,但我试图使它独特。我得到了1170的错误,但当我删除了英国,错误也被删除了。
我不完全明白为什么。