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
이 문제를 어떻게 해결할 수 있습니까?
편집 : 또한이 테이블에는 여러 열이있는 복합 기본 키가 있음을 지적해야합니다.
답변:
MySQL이 BLOB 또는 TEXT
열의 첫 번째 N 문자 만 색인 할 수 있기 때문에 오류가 발생합니다 . 필드 / 열 유형이있는 경우 오류가 주로 발생 그래서 TEXT
BLOB 나에 속하는 나 TEXT
또는 BLOB
같은 종류의 TINYBLOB
, MEDIUMBLOB
, LONGBLOB
, TINYTEXT
, MEDIUMTEXT
, 및 LONGTEXT
기본 키 또는 인덱스를 만들기 위해 노력하고있다. 전체 BLOB
또는 TEXT
길이 값이 없으면 MySQL은 가변적이고 동적 크기이므로 열의 고유성을 보장 할 수 없습니다. 따라서 BLOB
또는 TEXT
인덱스를 인덱스로 사용 하는 경우 MySQL이 키 길이를 결정할 수 있도록 N 값을 제공해야합니다. 그러나 MySQL은 TEXT
또는 에서 키 길이 제한을 지원하지 않습니다 BLOB
. TEXT(88)
단순히 작동하지 않습니다.
당신이에서 테이블 열을 변환 할 때 오류가 나타납니다 non-TEXT
와 non-BLOB
같은 입력 VARCHAR
및 ENUM
에 TEXT
나 BLOB
이미 고유 제한 조건 또는 인덱스로 정의 된 컬럼에 입력합니다. 테이블 변경 SQL 명령이 실패합니다.
이 문제에 대한 해결책 은 인덱스 또는 고유 제한 조건에서 TEXT
또는 BLOB
열 을 제거 하거나 다른 필드를 기본 키로 설정하는 것입니다. 그렇게 할 수없고 TEXT
또는 BLOB
열에 제한 을 설정하려면 VARCHAR
type 을 사용 하고 길이 제한을 시도 하십시오. 기본적 VARCHAR
으로 최대 255 자로 제한되며 선언 직후 괄호 안에 암시 적으로 제한을 지정해야합니다. 즉, VARCHAR(200)
최대 200 자로 제한됩니다.
가끔, 당신이 사용하지 TEXT
않거나 BLOB
관련 유형을 테이블에, 오류 1170가 나타날 수도 있습니다. VARCHAR
열을 기본 키로 지정 했지만 길이 또는 문자 크기를 잘못 설정 한 경우와 같은 상황에서 발생 합니다. VARCHAR
는 최대 256 자까지만 허용하므로 VARCHAR(512)
MySQL VARCHAR(512)
이 SMALLTEXT
데이터 유형 으로 자동 변환하도록 강제하는 것과 같은 것은 열이 기본 키 또는 고유 또는 고유하지 않은 인덱스로 사용되는 경우 키 길이에서 오류 1170으로 실패합니다. 이 문제를 해결하려면 VARCHAR
필드 크기로 256보다 작은 그림을 지정하십시오 .
참조 : MySQL 오류 1170 (42000) : 키 길이없이 키 사양에 사용 된 BLOB / TEXT 열
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
or COMPACT
행 형식 을 사용하는 InnoDB 테이블의 경우 767 바이트입니다 . 예를 들어, 당신은에 255 개 이상의 문자의 열 접두사 색인이 제한 히트 수 TEXT
또는 VARCHAR
utf8mb3 문자 집합 및 각 문자에 대한 3 바이트의 최대 가정, 열을. REDUNDANT
그리고 COMPACT
이 대답이 주어진 시간에 사용할 수있는 유일한 형식이었다.
다음과 같이 alter table 요청에서 키 길이를 지정할 수 있습니다.
alter table authors ADD UNIQUE(name_first(20), name_second(20));
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과 같습니다.
인덱스 문자 수를 2로 늘리면 어떻게 될지 살펴 보자 (N = 2).
+---------------+-----------+
| indexedValue | rows |
+---------------+-----------+
| ab | 1,2 |
| ad | 3 |
+---------------+-----------+
이 시나리오에서 IS = 2 / 3 = 0.66은 인덱스 선택성을 증가 시켰지만 인덱스 크기도 증가했음을 의미합니다. 속임수는 최소한의 숫자 N을 찾아 최대의 인덱스 선택성을 가져 오는 것 입니다.
데이터베이스 테이블에 대해 계산을 수행 할 수있는 두 가지 방법이 있습니다. 이 데이터베이스 덤프 에 대해 설명하겠습니다 .
테이블 직원의 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 접두사를 5 자리 접두사로 시작합니다.
+-----+--------+
| 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가 있으며 테이블에 백만 개의 행이 포함되어 있으면이 숫자가 어떻게 증가하는지 상상해보십시오.
텍스트 유형 열이있는 테이블에 색인을 추가 할 때이 오류가 발생했습니다. 각 텍스트 유형에 사용할 크기를 선언해야합니다.
크기를 괄호 안에 넣습니다 ()
너무 많은 바이트가 사용되는 경우 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 은 BLOB / 텍스트 인덱스를 처리하는 동안 MySQL에서 열을 인덱싱하는 최대 문자 수입니다.
참조 : http://dev.mysql.com/doc/refman/5.7/en/innodb-restrictions.html
이를 처리하는 또 다른 훌륭한 방법은 고유 제한 조건없이 TEXT 필드를 작성하고 TEXT 필드의 다이제스트 (MD5, SHA1 등)를 포함하는 형제 VARCHAR 필드를 추가하는 것입니다. TEXT 필드를 삽입하거나 업데이트 할 때 전체 TEXT 필드에 대한 요약을 계산하고 저장하면 빠르게 검색 할 수있는 전체 TEXT 필드 (일부 부분이 아닌)에 대해 고유 제한 조건이 있습니다.
또한이 필드에 인덱스를 사용하려면 MyISAM 스토리지 엔진과 FULLTEXT 인덱스 유형을 사용해야합니다.
지금까지 아무도 언급하지 않았습니다 ... 4 바이트 utf8mb4로 이모티콘을 저장할 수도 있습니다 (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의 경우 기본적으로 활성화됩니다. 따라서이 경우 인덱스 열에 VARCHAR (768)을 utf8mb4 (또는 이전 utf8의 경우 VARCHAR (1024))를 사용할 수 있습니다. innodb_large_prefix 옵션은 동작이 내장 MySQL 8이기 때문에 5.7.7부터 더 이상 사용되지 않습니다 (이 버전에서는 옵션이 제거됨).
UNIQUE
키가 있음을 의미합니까?