MetricSign
Start free
Medium severityschema

MySQL Error:
1071

What does this error mean?

MySQL weigert een index aan te maken omdat de sleutellengte de maximale limiet voor het opgegeven opslagformaat overschrijdt. Bij InnoDB met het COMPACT- of REDUNDANT-rijformaat geldt een limiet van 767 bytes per indexsleutel. Met utf8mb4-codering verbruikt elk teken 4 bytes, waardoor een gewone VARCHAR(255)-kolom al 1020 bytes aan indexruimte inneemt. In een data-pipeline ziet de engineer dit tijdens schema-initialisatie, dbt-migraties of wanneer een ETL-tool probeert een tabel aan te maken met een index op een tekstkolom. Het symptoom is een harde CREATE TABLE- of ALTER TABLE-fout die de gehele pipeline-run afbreekt.

Common causes

  • 1VARCHAR(255) met utf8mb4-codering gebruikt 4 bytes per teken, waardoor de indexsleutel uitkomt op 1020 bytes — ruim boven de 767-byte limiet van InnoDB COMPACT-rijformaat. Dit is veruit de meest voorkomende oorzaak bij recente MySQL-installaties.
  • 2Samengestelde index op meerdere grote VARCHAR-kolommen: als je een composite index maakt op bijv. (col_a VARCHAR(200), col_b VARCHAR(100)) met utf8mb4, is de gecombineerde sleutellengte (200+100)*4 = 1200 bytes, wat ook het COMPACT-formaat-limiet overschrijdt.
  • 3MySQL 5.6 of 5.7 zonder innodb_large_prefix=ON: standaard staat deze optie uitgeschakeld, waardoor ook DYNAMIC-rijformaat de 767-byte limiet aanhoudt. dbt-modellen die gedraaid worden op oudere MySQL-configuraties lopen hier tegenaan zonder expliciete server-configuratie.
  • 4Gebruik van het COMPACT of REDUNDANT rijformaat op een tabel, terwijl de rest van de database al op DYNAMIC staat. Dit gebeurt wanneer tabellen zijn gemigreerd van een oudere MySQL-versie of wanneer CREATE TABLE-statements geen expliciete ROW_FORMAT-clausule bevatten.
  • 5Index op een ENUM- of SET-kolom die intern als VARCHAR wordt behandeld bij complexe character sets, of op een VARBINARY-kolom met een lengte boven 767 bytes — minder frequent maar wordt gezien in data-warehouse staginglagen met binaire identifiers.
  • 6dbt seed-bestanden of externe tools (Airbyte, Fivetran) die automatisch een unieke index aanmaken op een tekstkolom als surrogaatsleutel, zonder rekening te houden met de doeldatabaseconfiguratie. De tool stuurt een standaard-DDL die op PostgreSQL werkt maar op oudere MySQL-versies faalt.
  • 7Migratie-tooling (Flyway, Liquibase) die een index aanmaakt via een changelog die oorspronkelijk geschreven was voor een andere MySQL-versie of character set. Het charset-verschil tussen omgevingen (dev utf8, prod utf8mb4) zorgt ervoor dat het schema werkt in ontwikkel maar faalt in productie.

How to fix it

  1. 1Stap 1 — Snel vaststellen welke kolom de limiet overschrijdt: voer `SHOW CREATE TABLE your_table;` uit en bekijk welke kolommen in de index zitten. Bereken: kolomlengte × bytes_per_char (utf8mb4 = 4, utf8 = 3, latin1 = 1). Als het totaal boven 767 bytes komt voor COMPACT of boven 3072 voor DYNAMIC, is dat de oorzaak.
  2. 2Stap 2 — MySQL 5.6/5.7: schakel innodb_large_prefix in voor een 3072-byte limiet met DYNAMIC-formaat: `SET GLOBAL innodb_large_prefix=ON; SET GLOBAL innodb_file_format=Barracuda;`. Maak vervolgens de tabel aan met `ROW_FORMAT=DYNAMIC` of voer `ALTER TABLE your_table ROW_FORMAT=DYNAMIC;` uit op bestaande tabellen.
  3. 3Stap 3 — MySQL 8.0+: controleer eerst het rijformaat van de tabel: `SELECT TABLE_NAME, ROW_FORMAT FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'jouw_db' AND TABLE_NAME = 'your_table';`. Staat het op COMPACT of REDUNDANT, converteer dan: `ALTER TABLE your_table ROW_FORMAT=DYNAMIC;`. In MySQL 8.0 is DYNAMIC de standaard voor nieuwe tabellen.
  4. 4Stap 4 — Prefix-index als snelle tijdelijke fix: beperk de geïndexeerde tekenlengtes tot 191 tekens voor utf8mb4 (191 × 4 = 764 bytes, net onder 767): `CREATE INDEX idx_col ON your_table (col(191));`. Voor een composite index: `CREATE INDEX idx_ab ON your_table (col_a(100), col_b(91));`. Let op: een prefix-index werkt niet voor UNIQUE-constraints waarbij de volledige kolomwaarde uniek moet zijn.
  5. 5Stap 5 — Bij dbt: voeg een `index_length` configuratie toe aan het model of pas de index-macro aan. Als de index puur voor lookupsnelheid is, overweeg een `not_null`+`unique`-test te vervangen door een prefix-index, of schakel de automatische unique-index uit via `unique_key` in dbt_project.yml en beheer de index handmatig via een post-hook: `{{ config(post_hook='CREATE INDEX ...') }}`.
  6. 6Stap 6 — Structurele oplossing voor tekst-identifiers: als de kolom een UUID, hash of URL bevat die volledig uniek geïndexeerd moet worden, overweeg dan de waarden op te slaan in een afzonderlijke INT/BIGINT surrogate-key kolom met AUTO_INCREMENT en de tekstkolom zonder index te laten of met een full-text index: `ALTER TABLE your_table ADD COLUMN id BIGINT AUTO_INCREMENT PRIMARY KEY;`.
  7. 7Stap 7 — Valideer na de fix: `SHOW INDEXES FROM your_table;` om te bevestigen dat de index aangemaakt is, gevolgd door een EXPLAIN op een representatieve query om te controleren dat de index ook daadwerkelijk gebruikt wordt. Voer bij dbt daarna `dbt run --select your_model` opnieuw uit en controleer dat de run succesvol is.

Example log output

ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes
[dbt] Compilation Error in model staging_customers (models/staging/staging_customers.sql)
  Database Error: 1071 (42000): Specified key was too long; max key length is 767 bytes

Frequently asked questions

Waarom is de limiet 191 tekens voor utf8mb4 VARCHAR-indexes?

InnoDB's standaard maximale sleutellengte is 767 bytes voor het COMPACT-rijformaat. utf8mb4 gebruikt maximaal 4 bytes per teken, dus 191 tekens × 4 bytes = 764 bytes — net onder de limiet. Met DYNAMIC-rijformaat (MySQL 8.0 standaard) ligt de limiet op 3072 bytes, waardoor VARCHAR(768) nog steeds past.

MySQL 1071 fix: wat is de snelste oplossing zonder server-configuratie te wijzigen?

Gebruik een prefix-index: `CREATE INDEX idx ON your_table (col(191));` voor utf8mb4-kolommen. Dit vereist geen wijzigingen aan de MySQL-serverconfiguratie en werkt op elke versie. Nadeel: de index kan niet gebruikt worden voor UNIQUE-constraints op de volledige kolomwaarde.

Krijg ik MySQL 1071 ook in MySQL 8.0?

Zelden — MySQL 8.0 gebruikt standaard DYNAMIC-rijformaat met een 3072-byte limiet, dus de meeste praktische VARCHAR-indexes passen. De fout kan nog steeds optreden bij tabellen die gemigreerd zijn vanuit oudere versies en nog het COMPACT-formaat hebben, of bij extreem lange composite indexes die ook 3072 bytes overschrijden.

Kan ik MySQL 1071 oplossen via dbt zonder de database te wijzigen?

Ja — voeg een post-hook toe aan het dbt-model die een prefix-index aanmaakt in plaats van een volledige index, of gebruik `{{ config(indexes=[{'columns': ['col'], 'length': 191}]) }}` als je dbt-adapter dit ondersteunt. Schakel automatische unique-key indexen uit via `unique_key: false` als de constraint al op applicatieniveau gewaarborgd wordt.

Source · dev.mysql.com/doc/mysql-errors/8.0/en/server-error-reference.html

Other schema errors