it-swarm.it

InnoDB crea errore tabella: "Dimensione riga troppo grande"

Abbiamo alcuni ingegneri che appiattiscono una struttura db normalizzata in una tabella temporanea allo scopo di generare un report. Le colonne sono specificate come TEXT NOT NULL (So "perché lo stanno facendo?"; Supponiamo che ci stiamo occupando di questo).

Utilizziamo MySQL 5.1.48 Community RHEL5 con plug-in InnoDB 1.0.9 su Linux.

Quando si utilizza MyISAM non abbiamo mai riscontrato limiti di dimensione della tabella per colonne massime o lunghezza massima della riga (durante l'indagine abbiamo raggiunto il limite massimo di colonne a 2598 (il 2599 causa errore 1117). Con InnoDB stiamo raggiungendo limiti. Questi limiti si manifestano durante la creazione del tabella (nessun inserimento di dati) come:

ERRORE 1118 (42000) alla riga 1: dimensione della riga troppo grande. La dimensione massima della riga per il tipo di tabella utilizzata, senza contare i BLOB, è 8126. È necessario modificare alcune colonne in TESTO o BLOB

Cerco risposte a quanto segue:

  1. Qual è la formula dettagliata per determinare le dimensioni delle righe quando si usano lotti di colonne v/v/b/t? Ho provato alcuni formati diversi usando varchar(N) colonne (dove N è compreso tra 1 e 512), il set di caratteri UTF8 (* 3) e tutte le colonne che la tabella prenderà fino al fallimento. Nessuna delle combinazioni che ho provato fornisce valori che corrispondono ai risultati dei test effettivi.

  2. Quali altri "costi generali" devo considerare nel calcolo delle dimensioni della riga?

  3. Perché il messaggio di errore cambia da 8126 a 65535 quando passo dalla creazione di tabelle con colonne varchar (109) a colonne varchar (110)?

11
Evan

Le risposte alle tue domande sono complesse, perché variano in InnoDB formato file . Oggi ci sono due formati, chiamati Antelope e Barracuda.

Il file del tablespace centrale (ibdata1) è sempre nel formato Antelope . Se usi file per tabella, puoi fare in modo che i singoli file utilizzino il formato Barracuda impostando innodb_file_format=Barracuda in my.cnf.

Punti di base:

  • Una pagina da 16 KB di dati InnoDB deve contenere almeno due righe di dati. Inoltre ogni pagina ha un'intestazione e un piè di pagina contenenti checksum di pagina e numero di sequenza del registro e così via. Ecco dove ottieni il tuo limite di un po 'meno di 8 KB per riga.

  • I tipi di dati a dimensione fissa come INTEGER, DATE, FLOAT, CHAR sono memorizzati in questa pagina di dati principali e vengono conteggiati per il limite della dimensione della riga.

  • I tipi di dati di dimensioni variabili come VARCHAR, TEXT, BLOB sono archiviati in pagine di overflow, quindi non vengono conteggiati completamente ai fini del limite di dimensioni della riga. In Antelope, fino a 768 byte di tali colonne sono archiviati nella pagina dei dati primari oltre a essere archiviati nella pagina di overflow. Barracuda supporta un formato di riga dinamico , quindi può memorizzare solo un puntatore di 20 byte nella pagina dei dati primari.

  • I tipi di dati di dimensioni variabili sono inoltre preceduti da 1 o più byte per codificare la lunghezza. E il formato di riga InnoDB ha anche una matrice di offset di campo. Quindi c'è una struttura interna più o meno documentata nella loro wiki . [EDIT] Dead link - qui sembra migliore ora.

Barracuda supporta anche un ROW_FORMAT = COMPRESSED per ottenere ulteriore efficienza di archiviazione per i dati di overflow.

Devo anche commentare che non ho mai visto una tabella ben progettata superare il limite della dimensione della riga. È un forte "odore di codice" che stai violando la condizione gruppi ripetuti della prima forma normale.

19
Bill Karwin

La mia situazione è leggermente diversa. Uno degli elementi di dati che devo memorizzare in ogni riga è potenzialmente molto grande. (Il campo dati è un LONGBLOB per un documento che può contenere più immagini incorporate. Il mio database di esempio contiene documenti di dimensioni comprese tra 25 e 30 MB, ma in alcuni casi questi documenti potrebbero essere più grandi.) Nessuna delle soluzioni che ho trovato online ha fornito sollievo . (Modificato il tipo di file InnoDB su Barracuda, aumentato la dimensione del file di registro, impostato il formato di riga su COMPRESSED.)

L'unica soluzione che ho trovato che ha funzionato per me era tornare a MySQL 5.5.x da MySQL 5.6.x.

1
David