Codice errore 1117 Troppe colonne; Limite di colonne MySQL sulla tabella


37

Ho una tabella con 1699 colonne e quando provo a inserire più colonne ottengo,

Codice errore: 1117. Troppe colonne

In questa tabella ho solo 1000 righe. Per me la cosa più importante è il numero di colonne. Ci sono delle limitazioni sul tavolo? Voglio creare 2000 colonne. È possibile?


22
Buon Dio, che diamine. Questo puzza di un progetto di database incredibilmente scadente. O forse stai usando lo strumento sbagliato per il lavoro. Forse dovresti guardare alla normalizzazione del database
Zoredache il

12
Ruota il monitor di 90 gradi. Più seriamente, MySQL (o quasi tutti gli altri RDBMS) non è progettato per QUESTE colonne.

11
E perché 2000 sensori dovrebbero portare a 2000 colonne? Riprogetta il tuo database. Crea una tabella di sensori separata o qualcosa del genere, ma NON aggiungere ogni sensore come una nuova colonna. È una cosa incredibilmente sbagliata da fare.

6
Numero massimo di tabelle ... whoa there! Probabilmente avrai bisogno solo di un paio di tavoli. Non prendere in considerazione la creazione di 2000 tabelle invece di 2000 colonne!

2
Per favore, per favore, per favore leggi sulla normalizzazione del database !

Risposte:


35

Perché dovresti creare una tabella con anche 20 colonne, figuriamoci 2000 ???

I dati garantiti e denormalizzati possono impedire la necessità di eseguire JOIN per recuperare molte colonne di dati. Tuttavia, se hai più di 10 colonne, dovresti fermarti e pensare a cosa potrebbe accadere sotto il cofano durante il recupero dei dati.

Se una tabella di colonne 2000 subisce SELEZIONA * DA ... DOVE, genererai grandi tabelle temporanee durante l'elaborazione, recuperando colonne non necessarie e creando molti scenari in cui pacchetti di comunicazione ( max_allowed_packet ) verrebbero sull'orlo di ogni query.

Nei miei primi giorni come sviluppatore, ho lavorato in un'azienda nel 1995, dove DB2 era il principale RDBMS. La società aveva un'unica tabella con 270 colonne, dozzine di indici e problemi di prestazioni nel recupero dei dati. Hanno contattato IBM e fatto consultare i consulenti sull'architettura del loro sistema, inclusa questa tabella monolitica. Alla società è stato detto "Se non si normalizza questa tabella nei prossimi 2 anni, DB2 fallirà nelle query che eseguono l'elaborazione Stage2 (tutte le query che richiedono l'ordinamento su colonne non indicizzate)." Ciò è stato detto a una società multimiliardaria di normalizzare una tabella di 270 colonne. Quanto più una tabella di colonne 2000.

In termini di mysql, dovresti compensare tale cattiva progettazione impostando opzioni comparabili all'elaborazione DB2 Stage2. In questo caso, tali opzioni sarebbero

La modifica di queste impostazioni per compensare la presenza di dozzine, figuriamoci centinaia, di colonne funziona bene se si dispone di TB di RAM.

Questo problema si moltiplica geometricamente se si utilizza InnoDB poiché sarà necessario gestire MVCC (Multiversion Concurrency Control) cercando di proteggere tonnellate di colonne con ogni SELECT, UPDATE e DELETE attraverso l'isolamento delle transazioni.

CONCLUSIONE

Non ci sono sostituti o cerotti che possono compensare la cattiva progettazione. Per favore, per il tuo buonsenso in futuro, normalizza quel tavolo oggi !!!


1
Potrei immaginare come farebbe la società quando glielo dicessero. Aggiungono hook svn o creano "Linee guida per le migliori pratiche DB" chiedendo agli sviluppatori di non ordinare colonne non indicizzate in SQL. Invece, eseguono l'ordinamento all'interno dell'applicazione implementando il proprio algoritmo di ordinamento dei dati di grandi dimensioni.
Gqqnbig

25

Ho difficoltà a immaginare qualsiasi cosa in cui il modello di dati possa legittimamente contenere 2000 colonne in una tabella correttamente normalizzata.

La mia ipotesi è che probabilmente stai facendo una sorta di schema denormalizzato "riempi gli spazi vuoti", in cui stai effettivamente memorizzando tutti i diversi tipi di dati in un'unica tabella e invece di suddividere i dati in tabelle separate e creare relazioni , hai vari campi che registrano quale "tipo" di dati è archiviato in una determinata riga e il 90% dei tuoi campi è NULL. Anche allora, però, voler arrivare a 2000 colonne ... yikes.

La soluzione al tuo problema è ripensare il tuo modello di dati. Se stai memorizzando una grande pila di dati chiave / valore associati a un dato record, perché non modellarlo in quel modo? Qualcosa di simile a:

CREATE TABLE master (
    id INT PRIMARY KEY AUTO_INCREMENT,
    <fields that really do relate to the
    master records on a 1-to-1 basis>
);

CREATE TABLE sensor_readings (
    id INT PRIMARY KEY AUTO_INCREMENT,
    master_id INT NOT NULL,   -- The id of the record in the
                              -- master table this field belongs to
    sensor_id INT NOT NULL,
    value VARCHAR(255)
);

CREATE TABLE sensors (
    id INT PRIMARY KEY AUTO_INCREMENT,
    <fields relating to sensors>
);

Quindi, per ottenere tutte le voci del sensore associate a un dato record "master", puoi semplicemente SELECT sensor_id,value FROM sensor_readings WHERE master_id=<some master ID>. Se è necessario ottenere i dati per un record nella mastertabella insieme a tutti i dati del sensore per quel record, è possibile utilizzare un join:

SELECT master.*,sensor_readings.sensor_id,sensor_readings.value
FROM master INNER JOIN sensor_readings on master.id=sensor_readings.master_id
WHERE master.id=<some ID>

E poi si unisce ulteriormente se hai bisogno di dettagli su cosa sia ciascun sensore.


18

È un sistema di misurazione con 2000 sensori

Ignora tutti i commenti che urlano sulla normalizzazione: ciò che stai chiedendo potrebbe essere una progettazione di database sensata (in un mondo ideale) e perfettamente ben normalizzata, è semplicemente molto insolita e, come sottolineato altrove, gli RDBMS di solito non sono progettati per queste colonne .

Anche se non stai raggiungendo il limite rigido di MySQL , uno degli altri fattori menzionati nel link ti sta probabilmente impedendo di andare più in alto

Come altri suggeriscono, potresti aggirare questa limitazione disponendo di una tabella figlio id, sensor_id, sensor_valueo, più semplicemente, potresti creare una seconda tabella per contenere solo le colonne che non si adatteranno alla prima (e utilizzare lo stesso PK)


1
Questo è vero. Quando gestisci i dati e il corrispondente SQL con grande cura, la tua risposta spicca ancora di più !!!
RolandoMySQLDBA

3
L'uso di una tabella figlio non è una "soluzione alternativa". Avere una colonna per ogni sensore è semplicemente un design errato (sbagliato). È come avere una colonna per ogni dipendente in un sistema di risorse umane o una colonna per ogni costruttore di automobili per un DB che gestisce i modelli di auto.
a_horse_with_no_name il

11
@a_horse - stai facendo ipotesi che dubito siano valide. È del tutto possibile che il numero di sensori sia sostanzialmente fisso, che tutti vengano letti contemporaneamente e che tutti i dati vengano restituiti ogni volta. Nel qual caso una colonna per sensore non è "sbagliata", ma semplicemente impraticabile date le limitazioni del database. Mi piace supporre che gli interrogatori non siano idioti fino a prova contraria e iUngi ha risposto con dignità di fronte a risposte molto inutili da parte della folla di San Francisco.
Jack Douglas,

2
@Jack Douglas: anche se tutte le tue assunzioni fossero vere (di cui dubito fortemente) la memorizzazione di ciascun valore del sensore nella propria colonna causerà problemi a lungo termine. Che dire di domande come "qual è il valore medio per i sensori da 10 a 50 e da 25 a 100 tra ieri e oggi"? o "Quale sensore ha avuto il valore di lettura più elevato lo scorso lunedì?". Prova a scrivere query per questo con 2000 colonne. L'uso di una tabella normalizzata risolverà a lungo termine più problemi di quanti ne risolveranno ora la soluzione 2000 colonne.
a_horse_with_no_name il

2
Certo, se i sensori memorizzano valori correlati, presumo che non siano correlati (ad esempio, stanno tutti misurando diversi tipi di cose piuttosto che sostanzialmente la stessa cosa in posizioni diverse). Potresti dubitarne, ma solo l'OP lo sa per certo - e non è impossibile in campo medico o scientifico.
Jack Douglas,

15

Limiti di conteggio delle colonne di MySQL 5.0 (enfasi aggiunta):

Esiste un limite rigido di 4096 colonne per tabella , ma il massimo effettivo può essere inferiore per una determinata tabella. Il limite esatto dipende da diversi fattori interagenti.

  • Ogni tabella (indipendentemente dal motore di archiviazione) ha una dimensione massima delle righe di 65.535 byte.I motori di archiviazione possono imporre ulteriori limiti a questo limite, riducendo l'effettiva dimensione massima della riga.

    La dimensione massima della riga limita il numero (e possibilmente la dimensione) delle colonne perché la lunghezza totale di tutte le colonne non può superare questa dimensione.

...

I singoli motori di archiviazione potrebbero imporre ulteriori restrizioni che limitano il conteggio delle colonne della tabella. Esempi:

  • InnoDB consente fino a 1000 colonne.

7

Prima un po 'più di fuoco, poi una vera soluzione ...

Sono per lo più d'accordo con le fiamme già lanciate contro di te.

Non sono d'accordo con la normalizzazione dei valori-chiave. Le domande finiscono per essere orribili; prestazioni anche peggiori.

Un modo "semplice" per evitare il problema immediato (limitazione del numero di colonne) è "partizionare verticalmente" i dati. Hanno, diciamo, 5 tavoli con 400 colonne ciascuno. Avrebbero tutti la stessa chiave primaria, tranne uno potrebbe essere AUTO_INCREMENT.

Forse sarebbe meglio decidere sulla dozzina di campi più importanti, metterli nella tabella "principale". Quindi raggruppare i sensori in modo logico e inserirli in diverse tabelle parallele. Con il corretto raggruppamento, potrebbe non essere necessario UNIRE tutti i tavoli in ogni momento.

Stai indicizzando qualcuno dei valori? Hai bisogno di cercarli? Probabilmente cerchi su datetime?

Se devi indicizzare molte colonne - punt.

Se devi indicizzarne alcuni, inseriscili nella tabella principale.

Ecco la vera soluzione (se applicabile) ...

Se non hai bisogno della vasta gamma di sensori indicizzati, allora non creare colonne! Sì, mi hai sentito. Invece, raccoglili in JSON, comprimi il JSON, memorizzalo in un campo BLOB. Risparmierai un sacco di spazio; avrai una sola tabella, senza problemi di limite di colonna; ecc. L'applicazione verrà decompressa e quindi utilizzerà JSON come struttura. Indovina un po? Puoi avere una struttura: puoi raggruppare i sensori in array, elementi multilivello, ecc., Proprio come vorrebbe la tua app. Un'altra "caratteristica" - è a tempo indeterminato. Se aggiungi più sensori, non è necessario modificare la tabella. JSON se flessibile in questo modo.

(La compressione è facoltativa; se il tuo set di dati è enorme, ti aiuterà con lo spazio su disco, quindi le prestazioni complessive.)


Questa è la migliore risposta effettiva. Va bene commentare che forse dovrebbe cercare di non avere così tante colonne, ma che la risposta accettata sia "non farlo" non risponde alla domanda. Anche se questo ragazzo non ha davvero bisogno di così tante colonne, forse qualcun altro che trova questo Q ha bisogno di così tante persone e ha bisogno di una vera risposta.
BoB3K,

@ BoB3K - Il mio ampio paragrafo dice cosa fare , date le informazioni disponibili sul problema come indicato. JSONevita le "troppe colonne"; l'indicizzazione delle colonne selezionate aiuta con le prestazioni.
Rick James,

3

Vedo questo come uno scenario possibile nel mondo dei big data, in cui potresti non eseguire il tradizionale tipo di query select *. Ci occupiamo di questo nel mondo della modellazione predittiva a livello di cliente, dove modelliamo un cliente su migliaia di dimensioni (tutte con valori pari a 0 o 1). Questo modo di archiviazione rende più semplici le attività di costruzione del modello a valle, ecc. Quando si hanno i fattori di rischio nella stessa riga e anche il flag di risultato nella stessa riga. Questo può essere normalizzato da un punto di vista dello storage con una struttura figlio principale, ma il modello predittivo a valle dovrà riconvertirlo in schema piatto. Usiamo redshift che fa l'archiviazione colonnare, quindi le tue 1000+ colonne quando carichi i dati, in realtà sono archiviate in un formato colonnare ...

C'è un tempo e un luogo per questo design. Assolutamente. La normalizzazione non è la soluzione per ogni problema.


Grazie per il commento. Se si desidera eseguire analisi con immagini, anche una piccola immagine a colori di 16x16 pixel richiede 16 * 16 * 3 numeri interi compresi tra 0 e 255 (3 numeri per descrivere il colore in uno su 16x16 pixel utilizzando i colori RGB). Cioè 768 colonne solo per i dati, a cui sarebbe necessario aggiungere una chiave.
VictorZurkowski,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.